Hashing to Negative值

时间:2017-05-09 12:21:17

标签: java hash

几乎是标题:我正在散列一堆名字(10000-ish),有些正在输出为负数。 (表格大小为20011)。

有问题的哈希函数是:

public static long hash2 ( String key ){
  int hashVal = 0;
    for( int i = 0; i < key.length(); i++ )
      hashVal = (37 * hashVal) + key.charAt(i);
  return hashVal % 20011;
}

我挖了一下,我想我必须要做一些事情“环绕”。但我不知道如何去做。

2 个答案:

答案 0 :(得分:2)

这是Integer Overflow的明显案例。正如您在问题中提到的那样,字符串最多可能有10000个字符,那么hashValue肯定会溢出,因为需要将值存储在37^10000左右。即使这样也会在长度为20的字符串中失败。

在数论中,

(A+B)%M = (A%M + B%M) % M;
(A*B)%M = (A%M * B%M) % M;

您应该在for循环中应用模运算。但是如果你在最后或执行for循环时进行模运算,两者都会给出相同的答案如果溢出没有发生。

所以相应地做出改变,

public static long hash2 ( String key ){
  int hashVal = 0;
    for( int i = 0; i < key.length(); i++ )
    {
      hashVal = (37 * hashVal) + key.charAt(i);
      hashVal%=20011;
    }
  return hashVal;
}

答案 1 :(得分:1)

hashVal是一个整数。您的哈希函数很可能导致整数溢出。

您可以使用Math.abs()轻松解决此问题,以确保hashVal为正数。 e.g。

hashVal = hashVal == Integer.MIN_VALUE ? 0 : Math.abs(hashVal);
return hashVal % 20011;

mod %是为了确保计算出的最终索引在表格的范围内(例如,如果它&gt; =&gt; = 20011,它就像你说的那样使用除法的余数。 #39;环绕&#39;)。