为啥在计算哈希码时使用 xor 运算符? [复制]

Posted

技术标签:

【中文标题】为啥在计算哈希码时使用 xor 运算符? [复制]【英文标题】:Why is the xor operator used in computing hash code? [duplicate]为什么在计算哈希码时使用 xor 运算符? [复制] 【发布时间】:2013-10-08 23:22:12 【问题描述】:

在这篇 MSDN 文章中 http://msdn.microsoft.com/en-us/library/ms132123.aspx 它讨论了 Class Equalitycomparer 并有一个例子。在这个关于比较盒子的例子中,它有这个类 -

class BoxSameDimensions : EqualityComparer<Box>

    public override bool Equals(Box b1, Box b2)
    
        if (b1.Height == b2.Height & b1.Length == b2.Length
            & b1.Width == b2.Width)
        
            return true;
        
        else
        
            return false;
        
    

    public override int GetHashCode(Box bx)
    
        int hCode = bx.Height ^ bx.Length ^ bx.Width;
        return hCode.GetHashCode();
    

我不明白这行 int hCode = bx.Height ^ bx.Length ^ bx.Width;

有人可以解释一下吗?为什么是异或?

【问题讨论】:

见***.com/q/371328/11683和***.com/q/263400/11683。 另见***.com/a/2334251/945456和csharpindepth.com/ViewNote.aspx?NoteID=27(后者解释了为什么异或实际上可能是一个坏主意) 【参考方案1】:

^ 运算符是bitwise exclusive-or operator。

在这种情况下,它被用作从三个整数生成哈希码的便捷方式。 (我不认为这是一个很好的方法,但这是一个不同的问题......)

奇怪的是,在构造了一个哈希码之后,他们又在上面使用了GetHashCode(),这对于一个 int 来说完全没有意义,因为它只会返回 int 本身——所以它是一个空操作。

他们应该是这样写的:

public override int GetHashCode(Box bx)

    return bx.Height ^ bx.Length ^ bx.Width;

这个 SO 答案解释了为什么 XOR 有时效果很好:Why are XOR often used in java hashCode() but another bitwise operators are used rarely?

注意:我不喜欢使用 xor 作为三个整数的哈希码的原因是:

a ^ b ^ a == b

换句话说,如果对哈希码有贡献的第一个整数和最后一个整数相同,则它们根本不会对最终哈希码有贡献 - 它们相互抵消,结果始终是中间整数。

如果你只使用两个整数,那就更糟了,因为:

a ^ a == 0

所以对于两个整数,对于它们相同的所有情况,哈希码都将为零。

【讨论】:

好的,谢谢!刚学这个,觉得很奇怪! 还值得注意的是,在越界整数算术是未定义行为的语言中,xor 运算符的优点是可以通过任何操作数组合产生已定义的行为,但在整数类型换行的语言中干净利落,加法同样快速简单,并且避免了您描述的问题案例。 那么如果我们可以保证整数列表是不同的,这是否可以被视为一种计算哈希码的好方法?【参考方案2】:

你可能知道 GetHashCode() 是一个函数,它应该将你的对象映射到数字中,这样两个不同的对象获得相同数字的概率应该尽可能低(显然这个数字应该总是相同的相同的对象+函数应该很快)。从所有布尔运算符(AND、OR、NOT、XOR)中,XOR 提供最佳位分布(查看 OR、AND、XOR 布尔表)。但是我建议您检查这种方法:What is the best algorithm for an overridden System.Object.GetHashCode?。 (使用素数分布属性的散列函数)。

【讨论】:

以上是关于为啥在计算哈希码时使用 xor 运算符? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥在使用这种复合形式时用 XOR 交换值会失败?

^ (XOR) 运算符有啥作用? [复制]

为啥通过 XOR 交换整数变量在一行中不起作用?

为啥两个字节上的 xor 运算符会产生一个 int?

Dan Bernstein 的 Djb2 哈希函数:当我们只能乘以 33 时,为啥还要使用按位运算符?

为啥我们在重载赋值中使用 return *this? [复制]