旋转哈希为16位

时间:2012-05-08 10:42:32

标签: c hash

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];

2 个答案:

答案 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