xor
karma yaparken kullanmak için tehlikeli bir varsayılan işlevdir. Bundan daha iyidir and
ve or
bu fazla bir şey ifade etmez.
xor
simetriktir, bu yüzden elemanların sırası kaybolur. Böylece "bad"
karma ile aynı birleştirir "dab"
.
xor
çift olarak aynı değerleri sıfıra eşler ve "ortak" değerleri sıfıra eşlemekten kaçınmalısınız:
Böylece (a,a)
0 ile eşlenir ve 0 ile (b,b)
eşlenir. Bu çiftler neredeyse her zaman rastlantısallığın ima edebileceğinden daha yaygın olduğu için, sıfırdan çok çarpışmanız gerekir.
Bu iki problemle, xor
yüzeyde yarı iyi görünen bir karma birleştirici olur, ancak daha fazla incelemeden sonra olmaz.
Modern donanımda, genellikle yaklaşık olarak hızlı ekleme xor
(muhtemelen bunu çıkarmak için daha fazla güç kullanır). Eklemenin doğruluk tablosu şuna benzerxor
söz konusu bite , ancak her iki değer 1 olduğunda da bir sonraki bite biraz gönderir. Bu, daha az bilgi sildiği anlamına gelir.
Yani hash(a) + hash(b)
daha iyidir hash(a) xor hash(b)
eğer ki a==b
, sonucudurhash(a)<<1
0 yerine.
Bu simetrik kalır; böylece "bad"
ve "dab"
aynı sonucu elde etmek sorun olmaya devam ediyor. Bu simetriyi mütevazı bir maliyetle kırabiliriz:
hash(a)<<1 + hash(a) + hash(b)
aka hash(a)*3 + hash(b)
. ( hash(a)
vardiya çözümünü bir kez hesaplamanız ve saklamanız tavsiye edilir). Bunun yerine herhangi bir tek sabit 3
, bijektif k
olarak kendi kendine bir " -bit" işaretsiz tamsayıyı eşler, çünkü işaretsiz tam sayılardaki harita 2^k
bazıları için matematik modülondur k
ve herhangi bir tek sabit göreceli olarak asaldır 2^k
.
Daha meraklı bir versiyon için, boost::hash_combine
etkili bir şekilde inceleyebiliriz :
size_t hash_combine( size_t lhs, size_t rhs ) {
lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
return lhs;
}
Burada , bazı ek ve bir xor seed
ile bir sabit (temelde rasgele 0
s ve 1
s - özellikle 32 bit sabit nokta fraksiyonu olarak altın oranın tersidir) ile bazı kaydırılmış versiyonlarını ekliyoruz . Bu sonları simetri ve gelen karma değerleri yani 0'a her bileşen karmaları hayal (fakir iseler bazı "gürültü" tanıtır - Yukarıdaki kolları de, bir karalama üreten 1
ve 0
her peşinde birleştirmek Benim saf. 3*hash(a)+hash(b)
Basitçe çıkışları a0
in O vaka).
(C / C ++ ile aşina olmayanlar için, a size_t
bellekteki herhangi bir nesnenin boyutunu tanımlamak için yeterince büyük olan işaretsiz bir tamsayı değeridir. 64 bit sistemde genellikle 64 bit işaretsiz bir tamsayıdır. 32 bit sistemde , 32 bit işaretsiz bir tam sayı.)