升压魔术数字:: hash_combine


94

所述boost::hash_combine模板函数采用一个散列(称为参考seed)和对象v。根据文档,它结合seedvby 的哈希

seed ^= hash_value(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);

我可以看到这是确定性的。我明白了为什么要使用异或。

我敢打赌,这种加法有助于将相似的值广泛地映射,因此探测哈希表不会崩溃,但是有人可以解释魔术常数是什么吗?


假设在许多计算机上,整数旋转成本与移位相同,则将表达式转换为:<code> seed ^ = hash_value(v)+ 0x9e3779b9 + rotl(seed,6)+ rotr(seed, 2); </ code>
John Yates

Answers:


140

幻数应该是32个随机位,其中每个均等地可能为0或1,并且这些位之间没有简单的相关性。查找此类字符串的一种常见方法是使用无理数的二进制扩展。在这种情况下,该数字是黄金分割率的倒数:

phi = (1 + sqrt(5)) / 2
2^32 / phi = 0x9e3779b9

因此,“随机地”包含此数字会更改种子的每一位;如您所说,这意味着连续的值将相距很远。包括旧种子的移位版本在内,可以确保即使hash_value()值的范围很小,差异也将很快分散到所有位中。


14
凉!当数论突然变得有用时,我喜欢它:)
Fred Foo

8
@larsmans我爱您突然使用'-非常合适!数论在所有案例中有99%就像“是的,很好...但是我有很多工作要做,对不起”。然后,正如您所说,“突然”,数论超级有用。它不像锤子,它在很多事情上都非常有用。取而代之的是,这就像一把手术刀在少数情况下非常有用。
2013年

5
@SamKellett如果您使用正确的括号数并得到0x9e3779b97f4a7800
Barry,

5
由于Python的浮点数精度不够,因此上述64位黄金分割率不正确。实际结果应为0x9e3779b97f4a7c15
kennytm 2015年

1
@kennytm你不是说0x9e3779b97f4a7c16吗?我的意思是,只有1折。
bit2shift

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.