boost :: hash_combine의 매직 넘버


94

boost::hash_combine템플릿 함수 (라는 해시 참조 소요 seed) 및 오브젝트 v. 문서 에 따르면 by seed의 해시와 결합 v됩니다.

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

이것이 결정적이라는 것을 알 수 있습니다. XOR이 사용되는 이유를 알았습니다.

이 추가는 유사한 값을 넓게 매핑하는 데 도움이되므로 해시 테이블을 조사하는 것이 분해되지는 않지만 누군가 마법 상수가 무엇인지 설명 할 수 있습니까?


많은 컴퓨터에서 정수 회전 비용이 시프트와 거의 동일하다는 점을 감안할 때 표현식을 <code> seed ^ = hash_value (v) + 0x9e3779b9 + rotl (seed, 6) + rotr (seed, 2); </ code>
John Yates

답변:


141

매직 넘버는 32 개의 임의 비트로 가정되며, 각각은 0 또는 1 일 가능성이 동일하며 비트간에 단순한 상관 관계가 없습니다. 이러한 비트의 문자열을 찾는 일반적인 방법은 무리수의 이진 확장을 사용하는 것입니다. 이 경우 그 숫자는 황금 비율의 역수입니다.

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

따라서이 숫자를 "무작위로"포함하면 시드의 각 비트가 변경됩니다. 당신이 말했듯이 이것은 연속적인 값이 멀리 떨어져 있음을 의미합니다. 이전 시드의 이동 된 버전을 포함하면 hash_value()값의 범위가 상당히 작 더라도 차이가 곧 모든 비트에 분산 될 것입니다.


14
멋있는! 숫자 이론이 갑자기 유용 해지면 좋아합니다. :)
Fred Foo

8
@larsmans 나는 당신의 '갑자기'사용을 좋아합니다-매우 적절합니다! 수 이론은 모든 경우의 99 %에서 "그래, 그거 멋지다 ...하지만 진짜 할 일이있어, 미안하다"와 같다. 그리고 당신이 '갑자기'라고 말했듯이, 수 이론은 매우 유용합니다. 그것은 그것의 망치처럼 아니라 오히려 일의 큰 숫자에 유용합니다. 대신 메스처럼 적은 수의 일 에 매우 유용합니다.
corsiKa 2013-08-16

5
@SamKellett겠습니까 작업은 더 나은 괄호의 정확한 수를 사용하고있어 경우0x9e3779b97f4a7800
배리

5
Python의 부동 소수점 숫자는 정밀도가 충분하지 않기 때문에 위의 64 비트 황금 비율이 올바르지 않습니다. 실제 결과는 0x9e3779b97f4a7c15.
kennytm 2015

1
@kennytm 의미하지 0x9e3779b97f4a7c16않습니까? 내 말은, 그것은 단지 1 오프입니다.
bit2shift

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.