Чарівне число в boost :: hash_combine


94

Функція boost::hash_combineшаблону приймає посилання на хеш (викликається seed) та об'єкт v. Згідно з документами , він поєднується seedз хешем vby

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

Я бачу, що це детерміновано. Я розумію, чому використовується XOR.

Б'юся об заклад, додавання допомагає широко зіставляти подібні значення, тому зондування хеш-таблиць не розбивається, але чи може хтось пояснити, що таке магічна константа?


Враховуючи, що на багатьох комп’ютерах ціле число обертається приблизно так само, як зміщення, було б корисно перетворити вираз на: <code> seed ^ = hash_value (v) + 0x9e3779b9 + rotl (seed, 6) + rotr (seed, 2); </code>
Джон Йейтс,

Відповіді:


140

Передбачається, що магічним числом є 32 випадкові біти, де кожен з однаковою ймовірністю дорівнює 0 або 1, і без простої кореляції між бітами. Поширеним способом знайти рядок таких бітів є використання двійкового розширення ірраціонального числа; у цьому випадку це число є зворотним золотим перетином:

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

Тож включення цього числа "випадковим чином" змінює кожен біт насіння; як ви кажете, це означає, що послідовні значення будуть далеко один від одного. Включаючи зміщені версії старого насіння гарантує, що навіть якщо у hash_value()них є досить невеликий діапазон значень, відмінності незабаром будуть розподілені по всіх бітах.


14
Класно! Мені подобається, коли теорія чисел раптом стає корисною :)
Фред Фу

8
@larsmans Мені подобається, як ти використовуєш "раптово" - це дуже доречно! Теорія чисел схожа на "так, це приємно ... але у мене є справжня робота, вибачте" в 99% всіх випадків. І тоді, як ви кажете, "раптово", теорія чисел надзвичайно корисна. Це не як молоток, де він досить корисний для великої кількості речей. Натомість це як скальпель, який надзвичайно корисний для невеликої кількості речей.
corsiKa

5
@SamKellett Працювало б ще краще, якби ви використали правильну кількість дужок і отримали0x9e3779b97f4a7800
Barry

5
Оскільки число з плаваючою комою Python не має достатньої точності, 64-бітні золоті пропорції, вказані вище, є неправильними. Фактичний результат повинен бути 0x9e3779b97f4a7c15.
kennytm

1
@kennytm Ви не маєте на увазі 0x9e3779b97f4a7c16? Я маю на увазі, це лише 1 знижка.
bit2shift

25

Погляньте на статтю DDJ Боба Дженкінса від 1997 року . Чарівна константа ("золотий перетин") пояснюється наступним чином:

Золотий перетин насправді є довільним значенням. Його метою є уникнення зіставлення всіх нулів з усіма нулями.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.