ChatGPT解决这个技术问题 Extra ChatGPT

boost::hash_combine 中的幻数

boost::hash_combine 模板函数采用对哈希(称为 seed)和对象 v 的引用。根据 docs,它将 seedv 的哈希组合为

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

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

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

鉴于在许多计算机上,整数旋转成本与移位大致相同,将表达式转换为: seed ^= hash_value(v) + 0x9e3779b9 + rotl(seed, 6) + rotr(seed, 2);

M
Mike Seymour

幻数应该是 32 个随机位,其中每个位同样可能是 0 或 1,并且位之间没有简单的相关性。找到一串这样的位的常用方法是使用无理数的二进制展开;在这种情况下,该数字是黄金比例的倒数:

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

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


凉爽的!当数论突然变得有用时,我喜欢它:)
@larsmans 我喜欢你对“突然”的使用——这非常合适!在 99% 的情况下,数论就像“是的,这很好……但我有真正的工作要做,对不起”。然后,正如你所说,“突然”,数论超级有用。它不像锤子,它对很多事情都很有用。相反,它就像一把手术刀,对少数事情非常有用。
@SamKellett 如果您使用正确数量的括号并得到 0x9e3779b97f4a7800 会更好
因为 Python 的浮点数没有足够的精度,所以上面的 64 位黄金比例是不正确的。实际结果应该是 0x9e3779b97f4a7c15
@kennytm 你不是说0x9e3779b97f4a7c16吗?我的意思是,它只有1折。
N
NPE

看看 DDJ article by Bob Jenkins from 1997。魔术常数(“黄金比例”)解释如下:

黄金比例确实是一个任意值。其目的是避免将全零映射到全零。