帮助在Java中使用Horner的规则和哈希函数?

时间:2010-05-01 21:36:21

标签: java hashtable

我正在尝试使用Horner的规则将单词转换为整数。我理解它是如何工作的,如果这个词很长,它可能会导致溢出。我的最终目标是在散列函数h(x)= x mod tableSize中使用转换后的整数。我的书建议,由于溢出,你可以“在计算Horner规则中的每个带括号的表达式之后应用mod运算符。”我并不完全明白这是什么意思。说表达式如下:

((14 * 32 + 15)* 32 + 20)* 32 + 5

我是否在每个带括号的表达式后使用mod tableSize并将它们一起添加?这个哈希函数和霍纳规则的例子会是什么样子?

3 个答案:

答案 0 :(得分:5)

这本书说你应该利用这些数学等价:

(a * b) mod m = ((a mod m) * (b mod m)) mod m
(a + b) mod m = ((a mod m) + (b mod m)) mod m

因此,

h = (((x*c) + y)*c + z) mod m

相当于

        _   _   _  _
h = (((x*c) + y)*c + z)

其中

  _
a * b = ((a mod m) * (b mod m)) mod m
  _
a + b = ((a mod m) + (b mod m)) mod m

基本上,对于每个基本加法和基本减法,您将其替换为mod操作数和mod结果的“高级”版本。由于基本乘法的操作数现在在0..m-1范围内,因此您获得的最大数字是(m-1)^2,如果m足够小,可以减轻溢出。

另见


顺便说一下,应该指出32对于这个类的哈希函数来说是一个可怕的乘数选择(因为它不是素数),特别是对于计算(因为它是2的幂)。更好的是31,因为:

  • 这是主要的(在数学上很重要!)
  • 它比一个2的幂小,所以它可以优化为更便宜的移位和减法
    • 31 * i == (i << 5) - i

答案 1 :(得分:2)

它们意味着用结果mod tableSize:

替换带括号的表达式的结果
((((14*32+15)%tableSize)*32+20)%tableSize)*32+5

答案 2 :(得分:1)

使用Java代码更容易理解这一点。我们应该在循环内的计算中的每一步应用模运算符:

public static int hashCode(String key) {
    int hashVal = 0;
    for (int j = 0; j < key.length(); j++) {
        // For small letters.
        int letter = key.charAt(j) - 96; 
        hashVal = (hashVal * 32 + letter) % arraySize; // mod
    }
    return hashVal;
}