在字符串上调用GetHashCode()时获取重复值的概率
我想知道在string
实例上调用GetHashCode()
方法时获取重复值的可能性。 例如, 根据这篇博文, blair
和brainlessness在x86机器上具有相同的哈希码(1758039503)。
大。
(对不起乔恩!)
在短字符串之间获得哈希冲突的可能性非常大 。 给定一组仅从普通单词中抽取的一万个不同的短字符串,该集合中存在至少一个冲突的概率约为1%。 如果你有八万个字符串,那么至少有一次碰撞的概率超过50%。
有关显示集合大小和碰撞概率之间关系的图表,请参阅我关于此主题的文章:
http://blogs.msdn.com/b/ericlippert/archive/2010/03/22/socks-birthdays-and-hash-collisions.aspx
小 – 如果你在谈论任意两个任意不等字符串碰撞的可能性。 (这将取决于字符串的“任意”程度,当然 – 不同的上下文将使用不同的字符串。)
大 – 如果你在谈论在任意字符串的大池中至少发生一次碰撞的可能性。 小的个人概率与生日问题不匹配。
这就是你需要知道的一切。 肯定存在会发生冲突的情况,并且必须给出只有2 32个可能的哈希码,并且超过许多字符串 – 因此, 鸽巢原则certificate至少一个哈希码必须具有多个字符串它会产生它。 但是,您应该相信哈希的设计非常合理。
您可以依赖它作为缩小特定字符串的可能匹配的一种非常好的方法。 这将是一组不寻常的自然发生的弦,它会产生很多碰撞 – 即使有一些碰撞,显然如果你可以将一个候选搜索范围从50K缩小到少于10个弦,这是一个相当大的胜利。 但是你不能依赖它作为任何字符串的唯一值。
请注意,.NET 4中使用的算法在x86和x64之间有所不同,因此该示例可能在两个平台上都无效。
我认为所有可能的说法都是“小而有限,绝对不是零” – 换句话说,你不能依赖GetHashCode()
为两个不同的实例返回唯一值。
在我看来,当您想要快速判断两个实例是否不同时,最好使用哈希码 – 而不是它们是否相同。
换句话说,如果两个对象具有不同的哈希码,则您知道它们是不同的,并且不需要进行(可能是昂贵的)更深入的比较。
但是,如果两个对象的哈希码相同,则必须继续比较对象本身以查看它们是否实际相同。
万一你的问题意味着一组字符串中碰撞的概率是多少,
对于n个可用插槽和m个占用项目:
概率。 在第一次插入时没有碰撞是1。
概率。 在第二次插入时没有碰撞是(n-1)/ n
概率。 在第3次插入时没有碰撞是(n-2)/ n
概率。 第m次插入时没有碰撞的是(n – (m – 1))/ n
m次插入后没有碰撞的概率是上述值的乘积:(n-1)!/((n-m)!* n ^(m-1))。
这简化为(n选择k)/(n ^ m)。
每个人都是对的,你不能假设0次碰撞,因此,说概率“低”可能是真的,但不允许你假设没有碰撞。 如果您正在查看哈希表,我认为标准是当您的哈希表大约为2 / 3rds时,您开始遇到重大冲突的问题。
我对466k英文单词的数据库进行了测试,并使用string.GetHashCode()
获得了48次碰撞。 MurmurHash给出了稍好的结果。 更多结果如下: https : //github.com/jitbit/MurmurHash.net
两个随机选择的字符串之间的冲突概率是1 / 2^(bits in hash code)
,如果散列是完美的,这是不可能或不可能的。