这个哈希函数会异常频繁地发生冲突吗?

时间:2011-06-08 21:57:19

标签: c# hash hash-collision hash-code-uniqueness

我有以下代码来生成对象的哈希:

public int GetHashCode(MyType obj)
{
   return (obj.Prop1.GetHashCode() + obj.Prop2.GetHashCode() + obj.Prop3.GetHashCode()).GetHashCode();
}

即。我添加了所有属性的哈希码,然后采用哈希值。

在审查中,一位同事建议这将过于频繁地发生碰撞。我不确定这是真的,因为:

  1. 鉴于哈希码在正数和负数之间选择频率相同并且它们四处传播,我认为我们没有获得关于这些数字总和的可能性的任何其他信息,而不是数字本身
  2. 如果它们的和是非随机的,哈希码被设计成使“靠近”的数字变得“相距很远”,因此将非均匀分布的值馈入函数不应该是问题
  3. 谁是对的?

    如果答案是针对特定语言的,那么它就在C#中。

3 个答案:

答案 0 :(得分:6)

假设Prop1,Prop2等属于int类型。通常只使用较低范围的整数。您的总和方法将比必要时更频繁地发生碰撞。

7的HasCode是7,在自己散列int时非常有意义。但是使用代码时,元组<7, 3><3, 7><8, 2>都将具有相同的哈希值。与简单的XOR相同而不是加法。

常见的方法是添加一些(素数)和移位:

public int GetHashCode(MyType obj)
{
  int hash = 0;
  unchecked
  {         
     hash += 19 * obj.Prop1.GetHashCode();
     hash += 31 * obj.Prop2.GetHashCode();
     hash += 37 * obj.Prop3.GetHashCode();
  }
  return hash;
}

数字19,31,37并不太重要。如果您愿意,可以使用OR或XOR代替+

答案 1 :(得分:2)

XORing会更好:

public int GetHashCode(MyType obj)
{
   return obj.Prop1.GetHashCode() ^ 
          obj.Prop2.GetHashCode() ^ 
          obj.Prop3.GetHashCode();
}

答案 2 :(得分:0)

您可以使用修改过的FNV HashCode生成器,一个非常类似的问题已被回答(由我) here