我了解在异或之前进行大量乘法运算应该有助于处理分布不均的操作数,但是为什么乘法器应该是质数呢?

相关:为什么散列函数应该使用质数模数呢?
关闭,但不是完全重复:为什么Java中String的hashCode()使用31作为乘数?


评论

我在这里并没有真正的答案(我的老实话会是“因为乔什·布洛赫(Josh Bloch)这样说!”)。
重复:stackoverflow.com/questions/1145217/…

为什么关闭?因子和模数显然不是同一件事。

我同意,我对重复的问题线程或对此问题的回答不满意。这可能只是因为我尚未理解答案。如果有人提供进一步的说明,将不胜感激。

我也没有看到与质数相乘的充分理由。我认为没有一个。

#1 楼

Computing Life博客上有一篇很好的文章,详细讨论了此主题。它最初是作为对我在问题中链接到的Java hashCode()问题的答复而发布的。根据文章:

素数是唯一的数字。它们的独特之处在于,由于使用了素数来构成素数,所以素数与任何其他数字的乘积具有最大的唯一性机会(不像素数本身那样唯一)。此属性在哈希函数中使用。
给定字符串“ Samuel”,您可以通过将每个组成数字或字母与质数相乘并将它们相加来生成唯一的哈希。这就是使用素数的原因。但是使用素数是一种古老的技术。这里的密钥是要理解的,只要您可以生成足够唯一的密钥,就可以使用其他哈希技术。在这里可以找到有关无素散列的更多信息。


#2 楼

与非质数相乘的循环重复模式比数字小得多。如果使用质数,则保证循环重复模式至少与质数一样大。

评论


不幸的是,这是不正确的。您需要乘法组的生成器来获得最大周期。这与素数无关。

– cip科
09年9月30日在17:03

#3 楼

我不确定您正在谈论的是哪种算法,但是通常此类算法中的常数必须是相对素数的。否则,您会得到循环,并且结果中不会显示所有可能的值。

在您的情况下,该数字可能不必为质数,而仅是某些其他数的质数,但可以首要保证。它还涵盖了其他幻数发生变化的情况。例如,如果您要讲取某个数字的最后一位,则乘数不必是2的倍数。因此,即使它不是素数也可以使用9。

#4 楼

考虑最简单的乘法:x2。

等效于左移。换句话说,它实际上并没有“随机化”数据,只是将数据移了过来。

与x4相同,或者是2的任意幂。原始数据是完整的,只是移位了。

现在,乘以其他数字(不是2的幂)的乘积并不明显,但是仍然或多或少存在相同的问题。原始数据是完整的或微不足道的。 (例如,x5与左移两位相同,然后在原始数据上相加)。

GetHashCode的要点是实质上尽可能随机地分布数据。乘以质数可确保答案不会像移位或向其自身添加数字那样简单的变换。

评论


@abelenky:字符串s的最常见哈希之一是31 * s [0] + 31 ^ 2 * s [1] + ... + 31 ^(n-1)* s [n-1]。 31是素数。 31的乘积与移位和减法相同(即a * 31 =(a << 5)-a)。那很简单。所有这些都是要指出使用素数的原因不仅仅是弄乱数据。

–杰森
09年9月28日在20:02

这种散列但乘数为33的散列称为djb散列。由于伯恩斯坦是数论方面的专家,因此不使用质数当然不是偶然的。

– cip科
09年9月30日在17:30

@Accipitridae:使用31的一个主要缺点是素数是一对匹配的连续字符的哈希贡献将是32的倍数,实际上丢失了5位。使用33将使贡献为34的倍数,后者只会损失一位。

–超级猫
15年2月21日在21:49