嗨,有人可以建议一个哈希函数来获取整数列表并返回一个新的integer
吗?它应该快速评估并且或多或少地抗碰撞。我计划在近似搜索算法中使用它(例如 LSH)
Java 的hashCode()
列表使用这个公式:
31 + SUM 31^(i+1) *a[i]
有人知道为什么它是抗碰撞的吗?我想这大约是 31 是一个素数,但不知道如何证明它。
嗨,有人可以建议一个哈希函数来获取整数列表并返回一个新的integer
吗?它应该快速评估并且或多或少地抗碰撞。我计划在近似搜索算法中使用它(例如 LSH)
Java 的hashCode()
列表使用这个公式:
31 + SUM 31^(i+1) *a[i]
有人知道为什么它是抗碰撞的吗?我想这大约是 31 是一个素数,但不知道如何证明它。
您的公式错误(倒数),实际上是:
SUM 31^(n-1-i) * a[i]
其中n
是列表的长度,我们也使用 a[-1] = 1。或者,如果你想单独拥有它,
31^n + SUM 31^(n-1-i) * a[i]
(和 Java 的整数一样,结果取模 2^32。)
Java 的hashCode()
for List (在 java.util.List 中指定,并且应该由此类的每个实现实现)在加密意义上不是抗冲突的。也就是说,不难发现碰撞。
给定任何包含多个元素的整数列表,我们可以将其中一个加 1,将下一个减 31(或相反),并获得第二个具有相同哈希码的列表。
例如,这两个列表[1, 0]
具有[0, 31]
相同的哈希码992 = 31·32 = (1·31 + 1)·31 + 0 = (1·31 + 0)·31 + 31
。
它对意外碰撞的抵抗力很弱,这确实与 31 是质数(即没有真正的除数)这一事实有关,并且“自然发生”的整数列表(或其他对象的哈希码)往往不会相差就这个数量。
当然,如果我们构建列表列表,每个列表都使用相同的哈希码策略,我们很容易发生冲突:[ [0, 1], [0, 0] ]
并且[ [0, 0], [1, 0] ]
具有相同的哈希码 31³+2·31²+31 = 31744。