Tôi muốn hàm băm có số lượng dài (64 bit) và tạo ra kết quả là 10 bit. Hàm băm tốt nhất cho mục đích đó là gì. Đầu vào về cơ bản là địa chỉ của các biến (Địa chỉ có 64 bit hoặc 8 byte trên Linux), vì vậy hàm băm của tôi nên được tối ưu hóa cho mục đích đó.Hàm băm từ 64 bit đến 10 bit
Trả lời
tôi sẽ nói somethig như thế này:
uint32_t hash(uint64_t x)
{
x >>= 3;
return (x^(x>>10)^(x>>20)) & 0x3FF;
}
Các kẻo đáng kể 3 bit không phải là rất hữu ích, như hầu hết các biến là 4-byte hoặc 8-byte aligned, vì vậy chúng tôi loại bỏ chúng. Sau đó, chúng tôi lấy 30 bit tiếp theo và trộn chúng lại với nhau (XOR) trong khối 10 bit mỗi.
Một cách tự nhiên, bạn cũng có thể lấy số (x>>30)^(x>>40)^(x>>50)
nhưng tôi không chắc liệu chúng có thực sự khác biệt trong thực tế hay không.
Vì bạn sử dụng xor-shift để trộn, tôi khuyên bạn nên sử dụng một trong số 275 cặp được biết với thời gian 2^64-1 trong ma trận 64x64 của chúng như được mô tả bởi Marsaglia, ví dụ (7,11,10) hoặc (21, 17,48). Vì điều này trộn lẫn các bit theo cách giả ngẫu nhiên mà không có sự kỳ quặc nào được biết đến, nó hợp lệ để xor với nhau tất cả các từ ngay trước khi thực hiện & 0x3ff. Bằng cách đó, mọi bit đầu vào phải có cơ hội ảnh hưởng đến tất cả các bit đầu ra. Có lẽ không hoàn toàn 50:50 được phân phối như trong một băm mật mã, nhưng tốt như bạn có thể nhận được. Ngoài ra, vẫn là một ý tưởng tuyệt vời, +1 – Damon
Tốt nhất cho hầu hết các bản phân phối là mod bằng một số nguyên tố, 1021 là số nguyên tố 10 bit lớn nhất. Không cần phải cắt các bit thấp.
static inline int hashaddress(void *v)
{
return (uintptr_t)v % 1021;
}
Nếu bạn nghĩ rằng hiệu suất có thể là một mối quan tâm, có một vài khuyết trên tay và chủng tộc họ trong chương trình thực tế của bạn. Microbenchmarks là chất thải; một sự khác biệt của một vài chu kỳ là gần như chắc chắn để được đầm lầy bởi hiệu ứng bộ nhớ cache, và kích thước vấn đề.
Tôi đã viết một đồ chơi chương trình-thấy một số địa chỉ thật trên stack, khu vực dữ liệu, và heap. Về cơ bản tôi đã tuyên bố 4 quả cầu, 4 người dân địa phương và đã làm 2 mallocs
. Tôi đã bỏ hai bit cuối cùng khi in các địa chỉ. Dưới đây là một đầu ra từ một trong những lần chạy:
20125e8
20125e6
20125e7
20125e4
3fef2131
3fef2130
3fef212f
3fef212c
25e4802
25e4806
Điều này nói với tôi:
- Các LSB sản lượng này (bit thứ 3 của địa chỉ) là thường xuyên 'bật' và 'tắt'. Vì vậy, tôi sẽ không thả nó khi tính toán băm. Giảm 2 LSB có vẻ đủ.
- Chúng tôi cũng thấy rằng có nhiều entropy trong các bit 8-10 thấp hơn. Chúng tôi phải sử dụng khi tính toán giá trị băm.
- Chúng tôi biết rằng trên máy 64 bit, virtual addresses are never more than 48 bits wide.
Những gì tôi sẽ làm gì tiếp theo:
/* Drop two LSBs. */
a >>= 2;
/* Get rid of the MSBs. Keep 46 bits. */
a &= 0x3fffffffffff;
/* Get the 14 MSBs and fold them in to get a 32 bit integer.
The MSBs are mostly 0s anyway, so we don't lose much entropy. */
msbs = (a >> 32) << 18;
a ^= msbs;
Bây giờ chúng ta chuyển thông tin này thông qua một decent 'half avalanche' hash function, thay vì cán của riêng của chúng tôi. 'Một nửa trận tuyết lở' có nghĩa là mỗi bit đầu vào được một cơ hội để ảnh hưởng đến bit tại vị trí tương đương và cao hơn :
uint32_t half_avalanche(uint32_t a)
{
a = (a+0x479ab41d) + (a<<8);
a = (a^0xe4aa10ce)^(a>>5);
a = (a+0x9942f0a6) - (a<<14);
a = (a^0x5aedd67d)^(a>>3);
a = (a+0x17bea992) + (a<<7);
return a;
}
Đối với một hash 10-bit, sử dụng 10 MSB của uint32_t
trả lại.Hàm băm tiếp tục hoạt động tốt nếu bạn chọn N
MSB cho hàm băm bit N
, tăng gấp đôi số lượng nhóm với mỗi bit bổ sung.
Tôi thấy hơi chán, vì vậy tôi đã viết chuẩn đồ chơi cho việc này. Không có gì lạ mắt, nó phân bổ một nhóm bộ nhớ trên heap và thử băm tôi mô tả ở trên. Nguồn có thể có từ here. Một ví dụ kết quả:
1024 xô, 256 giá trị được tạo ra, 29 collissions
1024 xô, 512 giá trị được tạo ra, 103 collissions
1024 xô, 1024 giá trị được tạo ra, 370 collissions
Next: Tôi đã thử hai băm khác được trả lời ở đây. Cả hai đều có hiệu suất tương tự. Có vẻ như: Chỉ cần chọn nhanh nhất;)
- 1. Lỗi AJAX ASP.NET AJAX/32-bit đến 64-bit
- 2. 32 bit int * 32 bit int = 64 bit int?
- 3. Java JDK 32 bit và 64 bit
- 4. SDK Android 32 bit hoặc 64 bit trên hệ điều hành Windows 64 bit?
- 5. Ứng dụng 32 bit hoặc 64 bit trên hệ điều hành 64 bit?
- 6. OK để chỉ sử dụng 64 bit bit băm sha1 làm id?
- 7. Trong các hệ thống 64 bit, một cột 32 bit chiếm ít không gian hơn một bit 64 bit?
- 8. 64 bit ODBC Exception
- 9. Ứng dụng Java 64 bit: Hệ điều hành 64 bit, JRE 64 bit và Ứng dụng 64 bit có yêu cầu không?
- 10. MSTest từ chối chạy 64 bit?
- 11. Biên dịch 32 bit Assembler trên 64 bit ubuntu
- 12. Chuyển đổi 32 bit dll sang 64 bit dll
- 13. Eclipse 32 bit chạy trên 64 bit JVM
- 14. javascript float từ/đến bit
- 15. Các thông số được chuyển khi gọi Printf từ bit asm 64 bit như thế nào?
- 16. Nhập 32 bit dll trong 64 bit .Net application
- 17. Xây dựng 32 bit với 64-bit llvm-gcc
- 18. Boost.Test trên Windows 64 bit
- 19. Làm thế nào để biên dịch chương trình C++ thành 64-bit trên máy 64 bit?
- 20. 64 bit enum trong C++?
- 21. Hiệu suất Java 64 bit
- 22. SWT trên Windows 64-bit
- 23. Câu hỏi nhanh 64-bit
- 24. Hàm băm 256 bit Python với đầu ra số
- 25. Xác định Windows 64 bit so với 32 bit
- 26. Tạo 32 bit JavaFX Native Bundle trong máy 64 bit
- 27. .net InstallUtil utility - 32 bit vs 64 bit
- 28. Hệ điều hành iPhone 64 bit hay 32 bit?
- 29. QtCreator trên linux: 32 bit so với 64 bit
- 30. chạy nhị phân 32 bit trên máy 64 bit
Thông tin về phân phối các giá trị 64 bit trong vũ trụ của bạn, bạn có thể cho chúng tôi không? –
Không có hàm băm "tốt nhất" cho tất cả các trường hợp. Bạn phải nghiên cứu phân phối và đặc điểm của số đầu vào của bạn. –
Đầu vào là địa chỉ của các biến trên Linux. – MetallicPriest