boost :: hash_combineのマジックナンバー


94

boost::hash_combineテンプレート関数は、ハッシュ(と呼ばれる参照取りseed)及びオブジェクトvdocsによると、それseedvby のハッシュと結合します

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

これは決定論的であることがわかります。XORが使用される理由がわかります。

追加は、類似した値を広く分離してマッピングするのに役立つので、ハッシュテーブルをプローブしても問題が発生しないと思いますが、誰かが魔法の定数を説明できますか?


多くのコンピューターでは、シフトとほぼ同じ整数回転コストであることを考えると、式を次のように変換することには利点があります。 2); </ code>
ジョンイェイツ、

回答:


140

マジックナンバーは32のランダムなビットであると想定されており、それぞれが0または1である可能性が等しく、ビット間の単純な相関関係はありません。そのようなビットの文字列を見つける一般的な方法は、無理数のバイナリ展開を使用することです。この場合、その数は黄金比の逆数です。

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

したがって、この数値を「ランダムに」含めると、シードの各ビットが変更されます。あなたが言うように、これは連続した値が遠く離れていることを意味します。古いシードのシフトバージョンを含めることで、hash_value()値の範囲がかなり小さい場合でも、すべてのビットにすぐに差異が広がるようになります。


14
涼しい!数論が突然役立つときに私はそれが好きです:)
Fred Foo

8
@larsmans「突然」の使用が大好きです-とても適切です!数論は、すべてのケースの99%で、「うん、それはいいことだ…でも、実際にやらなくてはならないことがある」のようなものです。そして、あなたが言うように、「突然」、数論は超超有用です。それは、それが多くのものにかなり役立つハンマーのようなものではありません。その代わり、それはメスが少数の事柄に非常に役立つようなものです。
corsiKa 2013

5
@SamKellett正しい数の括弧を使用して取得した場合、さらにうまく機能します0x9e3779b97f4a7800
Barry

5
Pythonの浮動小数点数は十分な精度がないため、上記の64ビットの黄金比は正しくありません。実際の結果はになるはずです0x9e3779b97f4a7c15
kennytm 2015年

1
@kennytmどういう意味0x9e3779b97f4a7c16ですか?つまり、1つだけです。
bit2shift

25

見てみましょう1997年からボブJenkinsのDDJの記事を。魔法定数(「黄金比」)は次のように説明されます。

黄金比は実際には任意の値です。その目的は、すべてのゼロをすべてゼロにマッピングすることを回避することです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.