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

Hash 一个32位哈希与两个16位哈希之间是否存在冲突率差异?,hash,32-bit,16-bit,collision,Hash,32 Bit,16 Bit,Collision,我正在研究一个系统,在这个系统中哈希冲突将是一个问题。本质上,有一个系统引用哈希表+树结构中的项。然而,该系统首先将包含结构中路径的文本文件编译成包含散列值的二进制文件。这样做是出于性能原因。但是,由于这种情况,冲突非常糟糕,因为结构无法存储具有相同哈希值的2个项;请求项目的部分没有足够的信息来知道它需要哪个项目 我最初的想法是,2个哈希,或者使用2种不同的算法,或者使用两次相同的算法,加上2种盐,会更抗冲突。对于不同的哈希算法,两个项目具有相同的哈希是不太可能的 出于空间原因,我希望将哈希值保

我正在研究一个系统,在这个系统中哈希冲突将是一个问题。本质上,有一个系统引用哈希表+树结构中的项。然而,该系统首先将包含结构中路径的文本文件编译成包含散列值的二进制文件。这样做是出于性能原因。但是,由于这种情况,冲突非常糟糕,因为结构无法存储具有相同哈希值的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名称空间列表中的每个唯一单词都有不同的哈希值(或者是我做错了)。这对我来说似乎已经足够好了,但它仍然困扰着我的大脑。

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

如果您担心冲突,请确保您使用的散列算法在散列数据方面做得很好(有些算法的编写只是为了快速计算,这不是您想要的),并增加散列的大小,直到您感到满意为止

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

因此,您将看到的碰撞数量应大致遵循泊松分布,即
λ=n*(n-1)*2-k-1
。由此可知,没有散列冲突的概率约为
e-λ
。对于32位和100个项目,在一个级别上发生冲突的几率约为百万分之一点五二五。如果你用足够多的不同数据集做了足够多的这件事,最终那些百万分之一的机会就会加起来

但请注意,您有许多正常大小的级别和一些较大的级别,较大的级别将对碰撞风险产生不成比例的影响。这是因为您添加到集合中的每件事物都可能与前面的任何事物发生冲突-越多的事物就意味着冲突的风险越高。因此,举例来说,一个包含1000个数据项的单一级别有大约1/10000的失败几率,这与包含100个数据项的100个级别的失败几率大致相同

如果散列算法没有正常工作,冲突的风险将迅速增加。多快在很大程度上取决于失败的性质


使用这些事实和您对应用程序使用情况的预测,您应该能够决定是否接受32位哈希的风险,或者是否应该升级到更大的值。

我有点担心使用相同的16位哈希算法和两个不同的salt值;然后这两个散列值就隐式相关了。@IraBaxter我说的是salt,但我认为我错了。我的意思是使用相同的算法,但第二次使用前缀值。该算法将字符串拖入并迭代每次更改has的每个字符,以使“ab”和“ba”具有不同的值。由于我不必担心相同字符串(散列点)上的冲突,所以在第二次运行之前加上一个值应该足以让在第一次运行之后具有相同散列的两个项目在第二次运行中具有不同的散列。(然后我想再次确认一下)@ira baxter:如果散列算法是加密安全的,那么就不应该有这种关联。但是这是一个不应该被忽略的if。@Exodist:我不是数学家,但是如果你的两个hash函数有算法关系,那么我希望两个结果中的位是相关的。不是以容易看到的方式。坦率地说,c