it-swarm.asia

0x9e3779b9 ve 0x9e3779b1 gibi "sihirli" karma sabitler nereden geliyor?

Karma tablolarla ilgili kodda, genellikle sabit 0x9e3779b9 veya bazen 0x9e3779b1 buluyorum. Örneğin

hash = n * 0x9e3779b1 >>> 24

Bu belirli değer neden kullanılıyor?

137
bkgs

0x9e3779b9, Altın Oran'ın kesirli kısmının 0.61803398875… (sqrt (5) -1)/2'nin ayrılmaz parçasıdır, 2 ^ 32 ile çarpılır.

Bu nedenle, eğer φ = (sqrt (5) +1)/2 = 1.61803398875 Altın Oran ise, hash fonksiyonu n * φ 'nın Nice saçılma özelliklerine sahip olan fraksiyonel kısmını hesaplar. Kendinizi ikna etmek için, sık kullandığınız e-tablonuzda (n, n*c-FLOOR(n*c)) Dağılım grafiği oluşturun, c yerine φ, e, π vb. Yerleştirin. Yanlış yaptığınızda bazı ilginç gerçek hayat sorunları https://lkml.org/lkml/2016/4/29/838 .

Bu yöntem genellikle "Altın Oranlı Karma" veya "Fibonacci Karma" olarak adlandırılır ve Donald Knuth (Bilgisayar Programlama Sanatı: Cilt 3: Sıralama ve Arama) tarafından popüler hale getirilmiştir. Teorik olarak sayı, çoğunlukla Steinhaus Konjonktürü'ne ( https://en.wikipedia.org/wiki/Three-gap_theorem ) ve Altın Oran φ.

Bazen, 0x9e3779b1 'A en yakın olan 0x9e3779b9' U da görebilirsiniz (ve bu modüler bir karma olmadığı için biraz "kargo kültü" gibi görünüyor). Benzer şekilde, 0x9e3779b97f4a7c15 Ve 0x9e3779b97f4a7c55 Bu sayıların 64 bit eşdeğerleridir.

220
32f

Diğer cevaplar, bu sihirli sayıların arkasındaki niyeti açıklıyor, ki bu muhtemelen bilmek istediğiniz şeydi. Ancak "nereden geldikleri" nin kötü programlama uygulamalarından geldiğini söyleyebiliriz. Sihirli sayılar kötüdür ve asla kullanılmamalıdır. Bahsedilen sabitlere uygun tanımlayıcı değişken isimleri verilmeli ve hatta tanımlandıkları yere yorumlar da eklenmelidir. Ardından, koddaki değerlerin her görünümü adlandırılmış değişken biçiminde olmalıdır. Bu değerlerle tanıştığınız kodlarda bu durumda, ilk etapta amaçlarına göre önceden düşünülmüş olmazdınız.

Örnek:

Kötü örnek - kullanır sihirli sayılar

hash = n * 0x9e3779b1

Daha iyi örnek - yorumlar ve anlamlı değişken ile

# Golden Ratio constant used for better hash scattering
# See https://softwareengineering.stackexchange.com/a/402543 
GOLDEN_RATIO = 0x9e3779b1
hash = n * GOLDEN_RATIO
30
isilanes
Karma tablolarla ilgili kodda, genellikle sabit 0x9e3779b9 veya bazen 0x9e3779b1 buluyorum

Diğer cevap, bu değerin neden kullanıldığını doğru bir şekilde açıkladı. Ancak, bu sabiti sık sık bulursanız, karma sel saldırılarına karşı genellikle savunmasız kod bulduğunuzu fark etmiyor olabilirsiniz.

Karma sel saldırılarına karşı iki strateji vardır:

  1. Gizli rastgele bir tohuma sahip güvenli bir hash fonksiyonu kullanın. Karma fonksiyonunuzun gizli bir rastgele tohumu yoktur. Murmurhash3_32 gizli bir rastgele tohuma sahiptir, ancak küçük iç durumdan dolayı tohumdan bağımsız çoklu kolleksiyonlara sahiptir. Kriptografik güvenliğe ve hala neredeyse kabul edilebilir performansa sahip en iyi hash fonksiyonu muhtemelen SipHash'tir. Ne yazık ki, SHA512 vb. Kadar yavaş olmasa da yavaştır.

  2. Hızlı hesaplanan bir karma işlevi kullanın (bulduğunuz karma işlevi veya Murmurhash3_32 gibi) ve her karma grubunu dengeli bir ikili arama ağacının köküne yapın. Bu nedenle, sıradan ayrı bir zincirleme karma tablosu, her bir kovayı bağlantılı bir liste olarak içerir; AVL ağacı veya kırmızı-siyah ağaç gibi dengeli bir ikili arama ağacı haline getirerek, hala en kötü durum performansını garanti edersiniz.

Bence (2) daha iyi çünkü SipHash çok yavaş. Ayrıca, işletim sistemi çekirdek alanında, önyükleme aşamasında erken bir gizli rastgele tohum oluşturmak için yeterli entropi olmayabilir, bu nedenle çekirdek alanında, önyüklemenin başında rasgele sayılar oluşturma olanağınız olmayabilir.

Karma tablolar yaygın olarak yanlış kullanılmaktadır. Birçok sistemi, sadece aynı kepçeye hash olan birçok değer göndererek pratik bir durma noktasına getirmek kolaydır.

5
juhist