2013-08-25 39 views
-3

我有一个名为Color类,它实现以下重写:字典和缓存

public override Int32 GetHashCode() 
{ 
    unchecked 
    { 
     Int32 hash = 23; 
     hash = (hash * 37) + m_Changes.GetHashCode(); 
     hash = (hash * 37) + m_Blue; 
     hash = (hash * 37) + m_Green; 
     hash = (hash * 37) + m_Random; 
     hash = (hash * 37) + m_RandomBlue; 
     hash = (hash * 37) + m_RandomGreen; 
     hash = (hash * 37) + m_RandomRed; 
     hash = (hash * 37) + m_Red; 

     return hash; 
    } 
} 

我想缓存以减少计算结果来:

public static Color Average(Color left, Color right, Double weight) 
{ 
    Color value; 
    Int32 key = left.GetHashCode()^right.GetHashCode()^weight.GetHashCode(); 

    if (!s_Averages.TryGetValue(key, out value)) 
    { 
     Double complement = 100.0 - weight; 

     Int32 red = (Int32)(((left.Red * complement) + (right.Red * weight))/100.0); 
     Int32 green = (Int32)(((left.Green * complement) + (right.Green * weight))/100.0); 
     Int32 blue = (Int32)(((left.Blue * complement) + (right.Blue * weight))/100.0); 
     Int32 random = (Int32)(((left.Random * complement) + (right.Random * weight))/100.0); 
     Int32 randomRed = (Int32)(((left.RandomRed * complement) + (right.RandomRed * weight))/100.0); 
     Int32 randomGreen = (Int32)(((left.RandomGreen * complement) + (right.RandomGreen * weight))/100.0); 
     Int32 randomBlue = (Int32)(((left.RandomBlue * complement) + (right.RandomBlue * weight))/100.0); 

     value = new Color(red, green, blue, randomRed, randomGreen, randomBlue, random, (left.Changes || right.Changes)); 
     s_Averages.Add(key, value); 
    } 

    return value; 
} 

结果当我在屏幕上绘制平均颜色时,出现错误像素,效果不佳。如果我恢复的方法无高速缓存的版本,一切工作正常:

public static Color Average(Color left, Color right, Double weight) 
{ 
    Double complement = 100.0 - weight; 

    Int32 red = (Int32)(((left.Red * complement) + (right.Red * weight))/100.0); 
    Int32 green = (Int32)(((left.Green * complement) + (right.Green * weight))/100.0); 
    Int32 blue = (Int32)(((left.Blue * complement) + (right.Blue * weight))/100.0); 
    Int32 random = (Int32)(((left.Random * complement) + (right.Random * weight))/100.0); 
    Int32 randomRed = (Int32)(((left.RandomRed * complement) + (right.RandomRed * weight))/100.0); 
    Int32 randomGreen = (Int32)(((left.RandomGreen * complement) + (right.RandomGreen * weight))/100.0); 
    Int32 randomBlue = (Int32)(((left.RandomBlue * complement) + (right.RandomBlue * weight))/100.0); 

    return (new Color(red, green, blue, randomRed, randomGreen, randomBlue, random, (left.Changes || right.Changes))); 
} 

这只能意味着他们键入我生成使用的GetHashCode不是唯一的。我如何管理这种缓存为我的颜色平均数获取唯一键值?

+0

为什么究竟是什么? D: –

+3

举例:为什么你认为这是一个合适的和唯一的密钥?:Int32 key = left.GetHashCode()^ right.GetHashCode()^ weight.GetHashCode(); –

+0

嗯,我不这么认为这是什么产生...这就是为什么我试图找到一个好的解决方案... –

回答

1

在这种情况下,我不认为你会得到一个唯一的密钥
但是你可以做的更好
这从如果切换左右你会得到相同的密钥受到影响。

Int32 key = left.GetHashCode()^right.GetHashCode()^weight.GetHashCode(); 
15^17^20 == 17^15^20 

这将减少键冲突

Int32 key = 17*left.GetHashCode()^23*right.GetHashCode()^weight.GetHashCode(); 

更重要的是可以使用UINT64键

UInt64 key = (((UInt64)left.GetHashCode() << 32) | (UInt64)right.GetHashCode())^((UInt64)weight.GetHashCode() << 30); 

,看看你,怎么平均水平。
所有这些颜色在计算中都被转换为Double,并且具有开销。
这到底有多确切?
如果weight和complement是Int32,会有一些舍入误差,但速度会更快。

Int32 iweight = (Int32)(weight*100); 
Int32 icomplement = 10000 - weight; 
Int32 red = ((left.Red * icomplement) + (right.Red * iweight))/10000; 

再次,这将有一些舍入误差,但它会更快。

为什么你使用Int32?
UInt16或Byte足够吗?
数学不是更快,但会减少内存。

+0

如果你会回答我问的问题,那么我可以改进答案。 – Paparazzi

+0

感谢您的回答。您的解决方案明智地减少了我的碰撞,但我仍然遇到它们。我是否有任何不同于使用Dictionary 或计算MD5/CRC32作为键的选择? –

+0

我再说一遍“如果你会回答我问的问题,那么我可以改进答案”。我当然不推荐Tuple。并且不要感谢+1 – Paparazzi