这个哈希函数背后的基本原理是什么?

时间:2011-10-17 09:56:22

标签: c hash

uint32_t h(const char *kbuf, int ksiz){
  uint32_t hash = 751;
  const char *rp = kbuf + ksiz;
  while(ksiz--){
    hash = (hash * 31) ^ *(uint8_t *)--rp;
  }
  return hash;
}

为什么要以这种方式计算哈希值,理由是什么?

2 个答案:

答案 0 :(得分:3)

您的哈希算法遵循相同的想法,导致修改后的Bernstein哈希和Fowler / Noll / Vo(参见例如this overview of existing hash algorithms)。

XORing字节是一种经典的哈希算法。但是,哈希值的最终分布远非最优,因此,增加了一个额外的混合步骤(在这种情况下乘以31)。

使用31作为乘数,由Josh Bloch在Effective Java中解释:

  

选择值31是因为它是奇数素数。如果它是均匀的   并且乘法溢出,信息将丢失,如   乘以2相当于移位。使用的好处   素数不太清楚,但它是传统的。 31的不错的财产是   乘法可以用移位和减法代替   为了更好的性能:31 * i ==(i <&lt; 5) - i。现代VM执行此操作   自动进行优化。

选择33作为原始伯恩斯坦哈希中的乘数可能遵循类似的推理;但是,如果散列性能不是您的主要考虑因素,那么通过选择一个能够实现更好分布的乘数,您可能会更好。如果您不想自己试验,Fowler / Noll / Vo可能是一个不错的选择。

答案 1 :(得分:1)

此实现尝试使输入到输出映射均匀,以便冲突也是一致的。换句话说,它试图避免这样的情况:对于某些哈希值,存在许多冲突而不是其他冲突的方式。它通过将原始伪随机生成器的值混合到生成的散列值中来实现。或者您可以反过来考虑它,作为输入数据中的PRNG混合。素数(751和31)有助于实现均匀性。当然,没有任何保证,因为精心挑选的输入你可以无视这些尝试。

有关详细信息,请参阅以下文章:
Hash Function - Uniformity
Linear congruential generator