xor
เป็นฟังก์ชั่นเริ่มต้นที่เป็นอันตรายที่จะใช้เมื่อทำการแฮช มันดีกว่าand
และor
แต่ก็ไม่ได้พูดอะไรมาก
xor
มีความสมมาตรดังนั้นลำดับขององค์ประกอบจึงหายไป ดังนั้นพระทัยกัญชารวมเช่นเดียวกับ"bad"
"dab"
xor
จับคู่ค่าที่เหมือนกันของคู่กับศูนย์และคุณควรหลีกเลี่ยงการจับคู่ค่า "ทั่วไป" กับศูนย์:
ดังนั้น(a,a)
แมปถึง 0 และ(b,b)
ได้รับการแมปเป็น 0 เนื่องจากคู่เหล่านี้มักพบบ่อยกว่าการสุ่มอาจบอกเป็นนัยว่าคุณจะพบกับการชนจำนวนมากที่ศูนย์เกินกว่าที่คุณควรจะเป็น
ด้วยปัญหาทั้งสองนี้xor
กลายเป็น combiner แฮชที่ดูดีครึ่งบนพื้นผิว แต่ไม่ใช่หลังจากการตรวจสอบเพิ่มเติม
บนฮาร์ดแวร์ที่ทันสมัยการเพิ่มมักจะเร็วเท่าxor
(อาจใช้พลังงานมากขึ้นเพื่อดึงสิ่งนี้ออกมายอมรับ) ตารางความจริงของการเพิ่มคล้ายกับxor
ในบิตของคำถาม แต่ยังส่งบิตไปยังบิตถัดไปเมื่อค่าทั้งสองเป็น 1 ซึ่งหมายความว่ามันลบข้อมูลน้อยลง
ดังนั้นhash(a) + hash(b)
จะดีกว่าhash(a) xor hash(b)
ถ้าa==b
ผลลัพธ์ออกมาเป็นhash(a)<<1
0
เรื่องนี้ยังคงสมมาตร ดังนั้น"bad"
และ"dab"
ได้รับผลลัพธ์เดียวกันยังคงมีปัญหา เราสามารถแบ่งสมมาตรนี้ด้วยราคาที่ไม่แพง:
hash(a)<<1 + hash(a) + hash(b)
hash(a)*3 + hash(b)
อาคา (คำนวณhash(a)
หนึ่งครั้งและแนะนำให้เก็บถ้าคุณใช้วิธีเปลี่ยนกะ) ใด ๆ คงแปลกแทนที่จะ3
bijectively แผนที่จะเป็น " k
บิต" จำนวนเต็มไม่ได้ลงนามกับตัวเองเป็นแผนที่ในจำนวนเต็มไม่ได้ลงนามเป็นแบบโมดูโลคณิตศาสตร์2^k
สำหรับบางคนk
และคงแปลก ๆ 2^k
ค่อนข้างสำคัญในการ
สำหรับรุ่นที่ยิ่งกว่านั้นเราสามารถตรวจสอบboost::hash_combine
ได้ซึ่งมีประสิทธิภาพ:
size_t hash_combine( size_t lhs, size_t rhs ) {
lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2);
return lhs;
}
ที่นี่เราเพิ่มบางเวอร์ชั่นที่seed
มีการเปลี่ยนแปลงด้วยค่าคงที่ (ซึ่งโดยทั่วไปจะเป็นแบบสุ่ม0
และ1
s - โดยเฉพาะอย่างยิ่งมันเป็นสิ่งที่ตรงกันข้ามกับอัตราส่วนทองคำเป็นเศษส่วนจุดคงที่ 32 บิต) ด้วยการเพิ่มและ xor แบ่งนี้สมมาตรและแนะนำบางคน "เสียง" ถ้าค่าแฮชที่เข้ามาไม่ดี (เช่นจินตนาการทุก hashes ส่วนประกอบ 0 - จับดังกล่าวข้างต้นได้ดีสร้าง smear ของ1
และ0
. s หลังจากแต่ละรวมของฉันไร้เดียงสา3*hash(a)+hash(b)
เพียง outputs 0
ใน กรณีนั้น)
(สำหรับผู้ที่ไม่คุ้นเคยกับ C / C ++ a size_t
คือค่าจำนวนเต็มที่ไม่ได้ลงนามซึ่งใหญ่พอที่จะอธิบายขนาดของวัตถุใด ๆ ในหน่วยความจำบนระบบ 64 บิตโดยปกติจะเป็นจำนวนเต็ม 64 บิตที่ไม่ได้ลงชื่อบนระบบ 32 บิต เป็นจำนวนเต็ม 32 บิตที่ไม่ได้ลงชื่อ)