一个32位哈希与两个16位哈希之间是否存在冲突率差异?

时间:2011-04-06 04:58:11

标签: hash 32-bit 16-bit collision

我正在研究一个哈希冲突会成为问题的系统。本质上,有一个系统引用散列表+树结构中的项。但是,有问题的系统首先将包含结构中路径的文本文件编译为包含散列值的二进制文件。这是出于性能原因而完成的。但是由于这种冲突非常糟糕,因为结构不能存储具有相同散列值的2个项目;要求物品的部分没有足够的信息来知道它需要哪一个。

我最初的想法是2次哈希,要么使用2种不同的算法,要么使用相同的算法两次,使用2种盐会更具抗冲突性。对于不同的散列算法,具有相同散列的两个项目是非常不可能的。

由于空间原因,我希望将哈希值保持为32位,所以我想我可以切换到使用两个16位算法而不是一个32位算法。但这不会增加可能的哈希值的范围......

我知道切换到两个32位哈希会更具抗冲突性,但我想知道切换到2个16位哈希是否至少比单个32位哈希有一些增益?我不是数学上最倾向的人,所以我甚至不知道如何开始检查答案,而不是强迫它......

系统的一些背景知识:

项目由人类命名,它们不是随机字符串,通常由没有空格的单词,字母和数字组成。它是一个嵌套的哈希结构,所以如果你有{a => {b => {c => 'blah'}}}你可以通过获得a / b / c的值得到'blah'的值,编译的请求将是直接序列中的3个哈希值,哈希值为a,b,然后是c。

当给定级别发生碰撞时,只有一个问题。顶级项目与较低级别之间的碰撞很好。你可以{a => {a => {...}}},几乎可以保证不同级别的碰撞(不是问题)。

在实践中,任何给定级别的哈希值都可能少于100个,并且在同一级别上没有任何值会重复。

为了测试我采用的散列算法(忘记了哪一个,但我没有发明它)我下载了整个CPAN Perl模块列表,将所有命名空间/模块拆分成唯一的单词,最后散列每个搜索碰撞,我遇到了0次碰撞。这意味着该算法对CPAN命名空间列表中的每个唯一字具有不同的散列值(或者我做错了)。这对我来说似乎已经足够好了,但它仍然在我脑中唠叨。

1 个答案:

答案 0 :(得分:9)

如果您有2个16位哈希值,即产生不相关的值,那么您刚刚编写了一个32位哈希算法。这不会比任何其他32位哈希算法更好或更差。

如果您担心碰撞,请确保您使用的散列算法可以很好地散列您的数据(有些只是为了快速计算,这不是您想要的),并且增加了哈希的大小,直到你感到舒服为止。

这提出了碰撞概率的问题。事实证明,如果您的收藏中有n件事物,那么会有n * (n-1) / 2对可能发生碰撞的事情。如果您使用k位散列,则单对碰撞的几率为2-k。如果你有很多东西,那么不同对碰撞的几率几乎是不相关的。这正是Poisson distribution描述的情况。

因此,您将看到的碰撞次数应大致遵循λ = n * (n-1) * 2-k-1的泊松分布。由此可见无哈希冲突的概率约为e。对于32位和100项,一级碰撞的几率约为1.1525万。如果你这么做的时间足够多,有足够多的不同数据,那么最终百万分之一的数据会加起来。

但请注意,您有许多正常大小的水平和一些大水平,大型水平会对您的碰撞风险产生不成比例的影响。这是因为你添加到集合中的每一件事都可能与任何先前的事情相冲突 - 更多的事情等于更高的碰撞风险。因此,例如,具有1000个数据项的单个级别在10,000个失败中具有大约1个机会 - 这与具有100个数据项的100个级别的风险大致相同。

如果散列算法没有正常工作,您的碰撞风险将迅速上升。多快取决于失败的性质。

使用这些事实以及您对应用程序使用情况的预测,您应该能够决定是否对32位哈希值的风险感到满意,或者是否应该将其提升到更大的范围。