web-dev-qa-db-ja.com

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

boost::hash_combineテンプレート関数は、ハッシュ(seedと呼ばれる)およびオブジェクトvへの参照を取ります。 docs によると、seedvのハッシュと結合します。

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

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

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

84
Fred Foo

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

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

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

126
Mike Seymour

1997年のBob JenkinsによるDDJ記事 をご覧ください。マジック定数(「黄金比」)は次のように説明されます。

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

23
NPE