编程语言
首页 > 编程语言> > 为什么GetHashCode方法需要在C#中进行移位

为什么GetHashCode方法需要在C#中进行移位

作者:互联网

这个问题已经在这里有了答案:            >            What is the best algorithm for an overridden System.Object.GetHashCode?                                    18个
根据MSDN GetHashCode方法:

public struct Point
{
    private int x;
    private int y;

    public Point(int x, int y)
    {
       this.x = x;
       this.y = y;
    }

    public override bool Equals(Object obj)
    {
       if (!(obj is Point)) return false;

       Point p = (Point) obj;
       return x == p.x & y == p.y;
    }

    public override int GetHashCode()
    { 
        return ShiftAndWrap(x.GetHashCode(), 2) ^ y.GetHashCode();
    } 

    private int ShiftAndWrap(int value, int positions)
    {
        positions = positions & 0x1F;

        // Save the existing bit pattern, but interpret it as an unsigned integer.
        uint number = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
        // Preserve the bits to be discarded.
        uint wrapped = number >> (32 - positions);
        // Shift and wrap the discarded bits.
        return BitConverter.ToInt32(BitConverter.GetBytes((number << positions) | wrapped), 0);
    }
}

我对ShiftAndWrap方法感到困惑,我知道这是用来避免生成冲突哈希码的.但是我有以下问题:

>为什么将参数位置设置为2?
>为什么该方法先进行右移(32位),然后进行左移正电子,它有特定含义吗?
>如上所述,该方法用于减少发生碰撞的情况. new Point(5,8)vs new Point(8,5),但是如果我创建一个类似于new Point(3,16)的对象,它将获得与new Point(5,8)相同的哈希码.这种方法的真正作用是什么?

解决方法:

我不能说为什么他们选择这种特殊的哈希码实现,但是关于这个问题:

  1. Why the method do right-shift (32-positions) first then do left-shift positons, Does it have specific meaning?

这里的ShiftAndWrap()方法是一种算法的通用实现,用于将一个值左移N位并将溢出回绕到末尾.因此,在进行移位之前,他们首先要获得最左边的N位,以便可以将其附加到末尾.

因此,如果我们仅使用8位值(字节)并使用value =(二进制)11010010和positions = 3进行调用,则调用ShiftAndWrap()的样子如下所示:

value = 11010010

positions = 3

wrapped = value >> (8 - positions)
        = 11010010 >> (8 - 3) 
        = 11010010 >> 5 
        = 00000110

result = value << positions | wrapped
       = 11010010 << 3 | 00000110 
       = 10010000 | 00000110 
       = 10010110

我们可以看到,返回值10010110是将11010010移三位并环绕结果的结果.

关于为什么他们不仅仅使用x ^ y的问题,我怀疑这是因为这将意味着Point(N,M)始终会产生与Point(M,N)相同的哈希码.通过对x值进行移位,我们可以得到一个哈希码,该哈希码不仅考虑x和y值,还考虑它们的顺序,而x ^ y会忽略它们的顺序.

在包含相同类型子组件的数据结构上进行哈希处理时,通常需要让哈希函数对每个子组件进行不同的处理,以使它们的位置很重要.例如,Java对字符串使用此哈希公式(此处^表示指数,而不是XOR):

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

我们可以看到每个字符都乘以31的不同幂,因此stop具有与pots不同的哈希码.

至于他们为什么选择2作为要转换的头寸的数目,这可能是任意的,或者他们可能已经进行了一些评估,以查看哪种偏移程度可能会产生最佳分布.

标签:gethashcode,c
来源: https://codeday.me/bug/20191111/2022854.html