昨天我正在浏览一些.net源代码,并看到了GetHashcode的几个实现,其中包含以下内容:
(i1 << 5) + i ^ i2
我理解代码在做什么以及为什么。我想知道的是为什么他们使用(i1&lt;&lt; 5) + i代替(i1&lt;&lt; 5) - i。
我见过的大多数框架都使用-i,因为它相当于乘以31这是素数,但微软的方式相当于乘以33,其中有11和3作为因子,因此不是素数。
这有没有合理的理由?有任何合理的假设吗?
答案 0 :(得分:3)
我在math.stackexchange.com上问了同样的问题:Curious Properties of 33。
数学家之间的猜想以及我对这个主题所做的研究让我相信答案就是这样:
好的,我发现了微软使用33的原因。这就是伯恩斯坦 哈希。事实证明,33有一些神奇的属性可以产生一个 哈希码的良好分布,理论上很少 知道为什么。
基本上,在熵和速度比较中,伯恩斯坦做得很好并且非常活泼。提出常数33的人丹·伯恩斯坦(Dan Bernstein)无法解释33的什么属性产生如此好的哈希分布。
已经写了几篇比较散列函数的论文,并且证实了这一发现,但没有进一步解释使用33的好处。此外,我无法找到为什么Java使用31代替。到目前为止,这似乎是一个数学和编程之谜。
答案 1 :(得分:0)
我不记得31是否是其中一个素数,但有些素数被Dictionary<K,V>
用作能力。如果您使用左侧字段不再影响所选的桶,则哈希退化。