关于c#:为什么xor运算符用于计算哈希码?

Why is the xor operator used in computing hash code?

本问题已经有最佳答案,请猛点这里访问。

在这个msdn文章中http://msdn.microsoft.com/en-us/library/ms132123.aspx它讨论了类EqualityComparer并有一个示例。-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;

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


^运算符是位异或运算符。

在本例中,它被用作从三个整数生成哈希代码的方便方法。(我认为这不是一个很好的方法,但这是另一个问题…)

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

他们应该这样写:

1
2
3
4
public override int GetHashCode(Box bx)
{
    return bx.Height ^ bx.Length ^ bx.Width;
}

这个答案解释了为什么XOR有时工作得很好:为什么XOR经常在Java HASCODE()中使用,但是很少使用另一个位运算符?

注意:我不喜欢将XOR用于三个这样的整数的哈希代码的原因是:

1
a ^ b ^ a == b

换句话说,如果产生哈希代码的第一个和最后一个int是相同的,那么它们根本就不会产生最终的哈希代码——它们相互抵消,结果总是中间的int。

更糟糕的是,如果你只使用两个整数,因为:

1
a ^ a == 0

所以对于两个整数,对于所有相同的情况,散列码都是零。


正如您可能知道的那样,gethashcode()是一个函数,它应该将对象映射到数字中,这样两个不同对象获得相同数字的概率应该尽可能小(显然,对于同一对象,这个数字应该总是相同的+函数应该是fas)。从所有布尔运算符(AND、OR、NOT、XOR)中,XOR给出了最佳的位分布(查看OR、AND、XOR布尔表)。但是,我建议您检查这种方法:对于重写的System.Object.GetHashCode,什么是最佳算法?(使用素数分布属性的哈希函数)。