This site给出了旋转哈希的描述如下。
unsigned rot_hash ( void *key, int len )
{
unsigned char *p = key;
unsigned h = 0;
int i;
for ( i = 0; i < len; i++ )
h = ( h << 4 ) ^ ( h >> 28 ) ^ p[i];
return h;
}
此处返回的值为32位。但是,我想返回一个16位的哈希值。为此,在循环中如下指定h
是否正确?考虑h
在这里被声明为16位整数。
for ( i = 0; i < len; i++ )
h = ( h << 4 ) ^ ( h >> 12 ) ^ p[i];
答案 0 :(得分:4)
最好保留大哈希,并且只在返回时截断,如:
for ( i = 0; i < len; i++ )
h = ( h << 4 ) ^ ( h >> 28 ) ^ p[i];
return h & 0xffff;
移位常数4和28可能不是最好的(简而言之:因为它们有一个共同的除数)
经过一些实验,我得到了以下的散列函数,它的目的是在较低位中具有最大熵(这样可以使用两个幂的表大小)(这是{{3中使用的那个) }}):
unsigned hash_mem(void *dat, size_t len)
{
unsigned char *str = (unsigned char*) dat;
unsigned val=0;
size_t idx;
for(idx=0; idx < len; idx++ ) {
val ^= (val >> 2) ^ (val << 5) ^ (val << 13) ^ str[idx] ^ 0x80001801;
}
return val;
}
不严格需要使用0x80001801的额外干扰,但如果散列项具有长公共前缀,则会有所帮助。如果这些前缀包含0x0值,它也会有所帮助。
答案 1 :(得分:2)
很难用哈希来谈论“正确”,因为任何确定性结果都可以被认为是正确的。也许散列分布不会那么好,但这个散列似乎并不是最强的。
根据您的建议,您获得的数字仍为32位数字,高16位不会为零。
最简单的做法是不做任何改变,并将结果转换为unsigned short
。