C# 这个散列函数会经常发生冲突吗?
我使用以下代码生成对象的哈希:C# 这个散列函数会经常发生冲突吗?,c#,hash,hash-collision,hash-code-uniqueness,C#,Hash,Hash Collision,Hash Code Uniqueness,我使用以下代码生成对象的哈希: public int GetHashCode(MyType obj) { return (obj.Prop1.GetHashCode() + obj.Prop2.GetHashCode() + obj.Prop3.GetHashCode()).GetHashCode(); } 也就是说,我添加所有属性的散列码,然后获取该属性的散列 在评论中,一位同事建议,这将导致碰撞过于频繁。我不确定这是真的,因为: 考虑到散列码在正数和负数之间以相同的频率选择,并且它们
public int GetHashCode(MyType obj)
{
return (obj.Prop1.GetHashCode() + obj.Prop2.GetHashCode() + obj.Prop3.GetHashCode()).GetHashCode();
}
也就是说,我添加所有属性的散列码,然后获取该属性的散列
在评论中,一位同事建议,这将导致碰撞过于频繁。我不确定这是真的,因为:
public int GetHashCode(MyType obj)
{
return obj.Prop1.GetHashCode() ^
obj.Prop2.GetHashCode() ^
obj.Prop3.GetHashCode();
}
对
假设Prop1、Prop2等的类型为int
。通常只使用较低范围的整数。你的求和方法会经常发生冲突
7
的HasCode是7,当它自己对int
进行散列时,这非常有意义。但是在代码中,元组
,
和
都具有相同的哈希值。简单的异或而不是加法也是如此
常用的方法是添加一些(素数)并移位:
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而不是
+
您可以使用经过修改的FNV哈希代码生成器,我已经回答了一个非常类似的问题
你同事的理由是什么?参见亨克·霍特曼的推理。如果某些属性的GetHashCode不使用整个范围,则与移位混合应提供更好的分布…素数很好,并且比移位更可取,因为简单的分块算法可能只取哈希代码的较低N位;如果属性发生移动,它们最终可能会被完全忽略。