Artışta sihirli sayı :: hash_combine


97

boost::hash_combineŞablon işlevi (denilen bir karma bir referans alır seed) ve bir nesne v. Göre docs , bu birleştirir seedve karma ile vtarafından

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

Bunun deterministik olduğunu görebiliyorum. XOR'un neden kullanıldığını anlıyorum.

Bahse girerim, ekleme benzer değerleri birbirinden geniş bir şekilde haritalandırmaya yardımcı olur, böylece araştırma hash tabloları bozulmaz, ancak birisi sihirli sabitin ne olduğunu açıklayabilir mi?


Pek çok bilgisayarda tamsayı döndürme maliyetinin bir vardiyayla hemen hemen aynı olduğu göz önüne alındığında, ifadeyi şu şekle dönüştürmenin herhangi bir faydası olacaktır: <code> seed ^ = hash_value (v) + 0x9e3779b9 + rotl (seed, 6) + rotr (seed, 2); </code>
John Yates

Yanıtlar:


143

Sihirli sayının 32 rastgele bit olması gerekiyordu, burada her biri eşit derecede 0 veya 1 olabilir ve bitler arasında basit bir korelasyon yoktur. Bu tür bitlerin bir dizisini bulmanın yaygın bir yolu, irrasyonel bir sayının ikili açılımını kullanmaktır; bu durumda, bu sayı altın oranın tersidir:

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

Yani bu sayının dahil edilmesi "rastgele" tohumun her bitini değiştirir; dediğiniz gibi, bu ardışık değerlerin birbirinden çok uzak olacağı anlamına gelir. Eski tohumun kaydırılmış versiyonlarının dahil edilmesi, hash_value()oldukça küçük bir değer aralığına sahip olsa bile , farklılıkların yakında tüm bitlere yayılacağını garanti eder .


15
Güzel! Sayı teorisinin aniden işe yaraması hoşuma gidiyor :)
Fred Foo

8
@larsmans 'Birdenbire' kullanımını seviyorum - bu çok uygun! Sayı teorisi, tüm vakaların% 99'unda "evet, bu güzel ... ama yapacak gerçek işlerim var, özür dilerim" gibidir. Ve sonra, dediğiniz gibi, 'aniden', sayı teorisi süper yararlıdır. Pek çok şey için oldukça kullanışlı olduğu bir çekiç gibi değil . Bunun yerine, az sayıda şey için son derece yararlı olan bir neşter gibi .
corsiKa

5
@SamKellett Doğru sayıda parantez kullanırsanız ve alırsanız daha iyi çalışırdı0x9e3779b97f4a7800
Barry

5
Python'un kayan nokta sayısı yeterli kesinliğe sahip olmadığından, yukarıdaki 64-bit altın oranlar doğru değildir. Gerçek sonuç olmalıdır 0x9e3779b97f4a7c15.
kennytm

1
@kennytm Bunu mu demek istiyorsunuz 0x9e3779b97f4a7c16? Demek istediğim, sadece 1 kez.
bit2shift

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.