2011-09-27 141 views
8

這個代碼塊中代字號的用途是什麼?波浪在這種情況下的目的是什麼?

public override int GetHashCode() 
    { 
     return ~this.DimensionId.Id^this.ElementId.Id; 
    } 

^運算符(C#參考) Visual Studio 2010中 二元^運算符預定義的整型和布爾。對於整型,^計算其操作數的按位異或。對於bool操作數,^計算邏輯異或操作數;也就是說,當且僅當其中一個操作數爲真時,結果纔是真的。

〜算符(C#參考) Visual Studio 2010中 操作符〜對其運算數執行,其具有反轉每個比特的效果的按位求補操作。按位補充運算符是爲int,uint,long和ulong預定義的。

〜(代字號)運算符對其單個整數操作數執行按位補碼。 (因此〜運算符是一元運算符,例如!和一元運算符,即&和*運算符)。補數表示將所有0位全部更改爲1,將所有1全部更改爲0

什麼是原因爲什麼它會在這種情況下使用(而不是簡單地排除它)?

+0

如果值很小,xor運算符往往會產生較差的散列分佈。翻轉這些位可以改變這一點。這實際上運作的可能性不好。將素數乘以1,並更好地添加作品。 –

回答

13

這只是生成哈希碼的一種方式。我並不是散列碼中的XOR的狂熱粉絲,除非你想要一些與順序無關的東西,但它是以合理的任意但可重複的方式翻轉位的合理方式。

基本上你在這裏有兩個32位值,你需要以某種形式組合以創建另一個32位值。代碼可能剛纔異或的值加在一起沒有任何位補:

return DimensionId.Id^ElementId.Id; 

...但總是給零其中ElementId.Id == DimensionId.Id,這可能是不理想的情況。另一方面,如評論(doh!)所述,如果兩個ID是相同的,我們現在總是以-1結尾。另一方面,它使得{6,4}對具有與{4,6}不同的散列碼,而簡單的XOR則不會......換言之,它使得排序很重要。同樣,如果您的標識符可能來自相對較小的池,那麼這可能很重要。

的XOR本身可以確保更改任何要麼 ID使最終散列碼的差異。我個人通常遵循Josh Bloch的有效Java模式,例如,

unchecked 
{ 
    int hash = 17; 
    hash = hash * 31 + DimensionId.Id; 
    hash = hash * 31 + ElementId.Id; 
    return hash; 
} 

...但是這只是因爲一些散列這樣的特性,並且不會讓你出任何意義上的「錯誤」的執行情況。


這似乎在一些常見的場景產生不同的值工作得很好。顯然它不能防止哈希衝突,但如果您的ID實際上是從1,2,3的序列中生成的,那麼這將在XOR的實際衝突中更好。我看到一個分析這種方法的網頁,哪些數字工作得很好等,但我不記得在哪裏。

+0

Jon Skeet-完全無知的問題:散列碼中XOR的替代/更好的方法是什麼? XOR是我知道做得好的唯一方式。 –

+0

@RitchMelton:當您評論時,我可能會將我的首選代碼放入...請參閱我的答案的底部。 –

+0

@Jon - 我是否在C#深度第二版中錯過這些運算符?無論如何,謝謝你的信息! –

相關問題