Số ma thuật tăng :: hash_combine


94

Hàm boost::hash_combinekhuôn mẫu nhận tham chiếu đến một hàm băm (được gọi seed) và một đối tượng v. Theo tài liệu , nó kết hợp seedvới các hash của vbằng

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

Tôi có thể thấy rằng điều này là xác định. Tôi hiểu tại sao XOR được sử dụng.

Tôi cá rằng việc bổ sung sẽ giúp ánh xạ các giá trị tương tự cách xa nhau một cách rộng rãi để việc thăm dò các bảng băm sẽ không bị hỏng, nhưng ai đó có thể giải thích hằng số ma thuật là gì không?


Giả sử rằng trên nhiều máy tính, chi phí xoay vòng số nguyên tương đương với một sự thay đổi sẽ có bất kỳ lợi ích nào trong việc chuyển đổi biểu thức thành: <code> seed ^ = hash_value (v) + 0x9e3779b9 + rotl (seed, 6) + rotr (seed, 2); </code>
John Yates

Câu trả lời:


140

Số ma thuật được cho là 32 bit ngẫu nhiên, trong đó mỗi bit đều có khả năng là 0 hoặc 1 và không có mối tương quan đơn giản giữa các bit. Một cách phổ biến để tìm một chuỗi các bit như vậy là sử dụng khai triển nhị phân của một số vô tỷ; trong trường hợp này, con số đó là nghịch đảo của tỷ lệ vàng:

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

Vì vậy, bao gồm số này "ngẫu nhiên" thay đổi từng bit của hạt giống; như bạn nói, điều này có nghĩa là các giá trị liên tiếp sẽ cách xa nhau. Bao gồm các phiên bản đã thay đổi của hạt giống cũ đảm bảo rằng, ngay cả khi hash_value()có một phạm vi giá trị khá nhỏ, sự khác biệt sẽ sớm lan rộng trên tất cả các bit.


14
Mát mẻ! Tôi thích nó khi lý thuyết số đột nhiên trở nên hữu ích :)
Fred Foo

8
@larsmans Tôi thích việc bạn sử dụng 'đột nhiên' - nó rất thích hợp! Lý thuyết số giống như "vâng, điều đó thật tuyệt ... nhưng tôi thực sự có việc phải làm, xin lỗi" trong 99% trường hợp. Và sau đó, như bạn nói, 'đột nhiên', lý thuyết số là siêu siêu hữu ích. Nó không giống như một cái búa mà nó khá hữu ích cho nhiều thứ. Thay vào đó, nó giống như một con dao mổ cực kỳ hữu ích cho một số việc nhỏ.
corsiKa

5
@SamKellett Sẽ hoạt động tốt hơn nữa nếu bạn sử dụng đúng số lượng dấu ngoặc đơn và nhận được0x9e3779b97f4a7800
Barry

5
Vì số dấu phẩy động của Python không có đủ độ chính xác nên tỷ lệ vàng 64-bit ở trên không chính xác. Kết quả thực tế nên được 0x9e3779b97f4a7c15.
kennytm

1
@kennytm Ý bạn không phải là 0x9e3779b97f4a7c16? Ý tôi là, nó chỉ có 1 lần tắt.
bit2shift

25

Hãy xem bài báo DDJ của Bob Jenkins từ năm 1997 . Hằng số ma thuật ("tỷ lệ vàng") được giải thích như sau:

Tỷ lệ vàng thực sự là một giá trị tùy ý. Mục đích của nó là tránh ánh xạ tất cả các số không thành tất cả các số không.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.