使用XOR和位移的字符串的哈希算法

时间:2014-08-13 07:07:47

标签: c++ algorithm hash xor bit-shift

我被赋予这个算法来编写一个哈希函数:

  

BEGIN哈希(字符串)
  UNSIGNED INTEGER键= 0;
  FOR_EACH字符IN字符串
  key =((key<<< 5)+ key)^ character;
  结束FOR_EACH
  返回键;
  结束哈希

<<运算符指向左侧的移位位。 ^指的是XOR操作,字符指的是字符的ASCII值。看起来非常简单。

以下是我的代码

unsigned int key = 0;
for (int i = 0; i < data.length(); i++) {
    key = ((key<<5) + key) ^ (int)data[i];
}
return key;

然而,当我真的应该从0 - n得到一个哈希值时,我会继续得到荒谬的正面和负面的巨大数字。 n是用户预先设置的值。我不确定哪里出了问题,但我认为这可能是XOR操作。

任何建议或意见将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:5)

此代码的输出是32位(或64位或宽{/ 1}}无符号整数)。要将其限制在0到 n -1的范围内,只需使用unsigned int运算符将其模数 n

%

(显而易见的是,您的代码,如写的,无法返回&#34;哈希值从0 - unsigned int hash = key % n; &#34;,因为n不会出现在代码中的任何位置。)

事实上,有一个很好的理由过早地减少模数 n 的哈希值:如果你需要增加哈希值,那么存储未减少的哈希值当 n 发生变化时,字符串的哈希码可以节省您重新计算它们的工作量。

最后,关于哈希函数的一些一般性注释:

  • 正如Joachim Pileborg上面所述,明确的n演员表是不必要的。如果你想保持清晰,那么确实应该(int)来匹配(unsigned int)的类型,因为这是实际转换成的值。

  • 对于无符号整数类型,key等于((key<<5) + key)(因为左移5位与乘以2 5 = 32相同)。在现代CPU上,使用乘法几乎肯定更快;在具有慢速乘法的旧的或非常低端的处理器上,任何体面的编译器都可能将乘法乘以常数优化为移位和加法的组合。因此,无论哪种方式,将操作表示为乘法都是IMO的首选。

  • 您不想在循环的每次迭代中调用33 * key。在循环之前调用它一次并将结果存储在变量中。

  • data.length()初始化为零意味着您的哈希值不受字符串中任何前导零字节的影响。由于Dan Bernstein,哈希函数的original version使用了(或多或少随机)的初始值5381。