我正在构建一个自定义哈希,我根据公式对字符串中的所有字母求和:
string[0] * 65536 + string[1] * 32768 + string[2] * 16384 + ...
Run Code Online (Sandbox Code Playgroud)
而且我遇到了一个问题,我是否应该将这些数字定义为int数组中的常量,如下所示:
const int MULTIPLICATION[] = {
65536,
32768,
16384,
8192,
4096,
2048,
1024,
512,
256,
128,
64,
32,
16,
8,
4,
2,
1
}
Run Code Online (Sandbox Code Playgroud)
或者,也许我应该在计算哈希本身时生成这些数字(虽然由于它们尚未生成而可能会失去一些速度)?我需要数百万次计算这个哈希值,我希望编译器理解的主要内容是代替普通的MUL操作
MOV EBX, 8
MUL EBX
Run Code Online (Sandbox Code Playgroud)
它会的
SHL EAX, 3
Run Code Online (Sandbox Code Playgroud)
编译器是否理解如果我乘以2的幂来移位而不是通常的乘法?
另一个问题,我很确定当你用c ++编号*= 2时,它会移位.但只是为了澄清,是吗?
谢谢,我已经找到了如何在调试器中查看dissasembly.是的,如果您使用它,编译器确实理解移位
number *= 65536
Run Code Online (Sandbox Code Playgroud)
但是,如果你这样做,它会进行正常的乘法运算
number1 = 65536
number *= number1;
Run Code Online (Sandbox Code Playgroud)
试试吧!
你用的是什么编译器?您可以告诉大多数编译器在编译后保留中间文件,或者只编译(而不是汇编),这样您就可以实际查看它生成的汇编代码.
你可以看到我的另一个问题,这就是我所做的.
例如,在gcc中,-S标志表示"仅编译".并-masm=intel生成更易读的程序集,IMO.
编辑
总而言之,我认为以下是您正在寻找的算法(未经测试):
// Rotate right by n bits
#define ROR(a, n) ((a >> n) | (a << (sizeof(a)*8-n)))
int custom_hash(const char* str, int len) {
int hash = 0;
int mult = 0x10000; // 65536, but more obvious
for (int i=0; i<len; i++) {
hash += str[i] * mult;
mult = ROR(mult, 1);
}
return mult;
}
Run Code Online (Sandbox Code Playgroud)
首先,你没有指定当你有超过16个字符时会发生什么(乘数是多少?)所以在这个实现中,我使用了一个按位旋转.86具有逐位循环指令(ror和rol分别旋转左,右).但是,C没有提供表达旋转操作的方法.所以我定义了ROR为你做旋转的宏.(了解它的工作原理留给读者练习!)
在我的循环中,我像你一样在0x10000(65536)开始乘数.循环的每次迭代,我将乘数右旋一位.这基本上将它除以2,直到达到1,之后变为0x80000000.