2013-08-25 66 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