我写了以下方法:
public static int hash2(String key, int tableSize) {
int hashVal = 0;
for(int i=0; i<key.length();i++) {
hashVal = 37 * hashVal + key.charAt(i);
}
System.out.println(hashVal);
hashVal %= tableSize;
if(hashVal < 0){
hashVal += tableSize;
}
return hashVal;
}
我的任务是重写for循环而不使用任何乘法或除法。我唯一的工具是添加和移位16位二进制数。
我意识到我需要以某种方式将hashVal乘以37,然后将key.charAt(i)添加到此值。我尝试过多种方式:
for(int i=0; i<key.length();i++) {
hashVal2 = hashVal2<<19 - hashVal2;
hashVal2 += key.charAt(i);
}
或
for(int i=0; i<key.length();i++) {
hashVal2 = hashVal2<<18 + hashVal2;
hashVal2 += key.charAt(i);
}
或
for(int i=0; i<key.length();i++) {
for(int j=0; j<37;j++) {
hashVal2 += hashVal2;
}
hashVal2 += key.charAt(i);
}
但是这些都不会像原始方法那样返回hashVal(或hashVal2)的相同值。我是否误解了位移,或者是循环的罪魁祸首?不知道还有什么可以尝试。
答案 0 :(得分:4)
乘以37与添加2的某些幂相同:
x * 37 == x * (32 + 4 + 1)
这告诉你如何转移,因为:
32 == 2 5
4 == 2 2
1 == 2 0
最后,对于所有i,x * 2 i ==(x <&lt; i)。因此,要将x乘以37,您可以计算
(x << 5) + (x << 2) + (x)
其余的练习应该相当简单。
答案 1 :(得分:1)
左移1位会将数字乘以2。 所以乘以37将37转换成二进制。这将是100101
Number * 2^5 + Number * 2^2 + Number * 2^0
Number << 5 + Number << 2 + Number
For循环看起来像这样:
for(int i=0; i<key.length();i++) {
hashVal = (hashVal << 5) + (hashVal << 2) + hashVal + key.charAt(i);
}