乘法时避免整数溢出的有效方法是什么?

时间:2010-05-04 19:02:26

标签: c hash

我正在处理一个哈希函数,它将一个字符串作为输入。

现在我正在做一个循环,并在散列内部(一个int变量)乘以一个值,然后将当前字符的ASCII代码添加到混合中。

hash = hash * seed + string[i]

但有时,如果字符串足够大,那里有整数溢出,我可以做些什么来避免它同时保持相同的散列结构?可能在循环中包含了一些操作吗?

4 个答案:

答案 0 :(得分:1)

像这样的哈希函数应该溢出。你必须声明“hash”unsigned。如果你真的需要一个int而不是简单地使用hash&为0x7FFFFFFF。查看Fowler-Noll-Vo algorithm,您会在那里找到源代码的链接。

答案 1 :(得分:1)

您的问题有多种可能的解释,正如评论中所述,您可能需要澄清。

然而,唯一明智的解释是您希望将哈希值限制为指定范围。假设,那么如果范围是0到HASH_TABLE_SIZE - 1,那么:

hash = (hash * seed + string[i]) % HASH_TABLE_SIZE ;

或如果表格大小是2的幂,请使用掩码:

#define HASH_TABLE_SIZE (0x01<<8)  // 2^8 (256) table
#define HASH_MODULO_MASK (HASH_TABLE_SIZE - 1)
...
hash = (hash * seed + string[i]) & HASH_MODULO_MASK ;

答案 2 :(得分:0)

为什么不用long来存储结果?然后,您可以应用技术such as this one来检测溢出

答案 3 :(得分:0)

如果您可以访问更大的数据类型,则可以执行以下操作:

int32_t hash, seed;
int64_t temporary;

temporary = hash * seed + string[i];
hash = ( temporary >> 32 ) ^ ( temporary & 0xFFFFFFFF );

否则你必须手动将散列和种子乘以两个值,将string [i]与overflow相加,然后将^这两个值相加。

哈希隐式有损,所以只要让溢出位去,除非有特殊原因需要它们,就像匹配现有算法一样。