Tóm tắt: Đó không phải là sự trùng hợp ngẫu nhiên; _PyHASH_INF
được mã hóa thành 314159 trong triển khai CPython mặc định của Python và được chọn là giá trị tùy ý (rõ ràng là từ các chữ số của π) bởi Tim Peters vào năm 2000 .
Giá trị của hash(float('inf'))
là một trong các tham số phụ thuộc hệ thống của hàm băm tích hợp cho các kiểu số và cũng có sẵn như sys.hash_info.inf
trong Python 3:
>>> import sys
>>> sys.hash_info
sys.hash_info(width=64, modulus=2305843009213693951, inf=314159, nan=0, imag=1000003, algorithm='siphash24', hash_bits=64, seed_bits=128, cutoff=0)
>>> sys.hash_info.inf
314159
(Kết quả tương tự với PyPy cũng vậy.)
Về mặt mã, hash
là một hàm tích hợp. Gọi nó trên một đối tượng phao Python gọi hàm mà con trỏ được đưa ra bởi các tp_hash
thuộc tính của các loại built-in float ( PyTypeObject PyFloat_Type
), mà là các float_hash
chức năng, định nghĩa như return _Py_HashDouble(v->ob_fval)
, mà lần lượt có
if (Py_IS_INFINITY(v))
return v > 0 ? _PyHASH_INF : -_PyHASH_INF;
trong đó _PyHASH_INF
được định nghĩa là 314159:
#define _PyHASH_INF 314159
Về mặt lịch sử, lần đầu tiên đề cập đến 314159
trong bối cảnh này trong mã Python (bạn có thể tìm thấy điều này bằng git bisect
hoặc git log -S 314159 -p
) đã được Tim Peters thêm vào tháng 8 năm 2000, trong đó hiện đang cam kết 39dce293 trong cpython
kho git.
Thông báo cam kết cho biết:
Khắc phục sự cố cho http://sourceforge.net/bugs/?func=detailorms&orms_id=111866&group_id=5470 . Đây là một lỗi gây hiểu lầm - "lỗi" thực sự là hash(x)
đã trả lại lỗi khi x
là vô cực. Đã sửa lỗi đó. Đã thêm Py_IS_INFINITY
macro mới vào
pyport.h
. Sắp xếp lại mã để giảm sự trùng lặp ngày càng tăng trong việc băm số float và số phức, đẩy cú đâm trước đó của Trent vào kết luận hợp lý. Đã sửa lỗi cực kỳ hiếm khi băm phao có thể trả về -1 ngay cả khi không có lỗi (không lãng phí thời gian để cố gắng xây dựng trường hợp thử nghiệm, đơn giản là rõ ràng từ mã có thể xảy ra). Cải thiện hàm băm phức tạp để
hash(complex(x, y))
không còn hệ thống bằng nhau hash(complex(y, x))
nữa.
Đặc biệt, trong cam kết này, ông tách ra mã của static long float_hash(PyFloatObject *v)
trong Objects/floatobject.c
và làm cho nó chỉ return _Py_HashDouble(v->ob_fval);
, và trong định nghĩa của long _Py_HashDouble(double v)
trong Objects/object.c
anh thêm các dòng:
if (Py_IS_INFINITY(intpart))
/* can't convert to long int -- arbitrary */
v = v < 0 ? -271828.0 : 314159.0;
Vì vậy, như đã đề cập, đó là một sự lựa chọn tùy ý. Lưu ý rằng 271828 được hình thành từ một vài chữ số thập phân đầu tiên của e .
Cam kết sau này:
hash(float('nan'))
là0
.