Ringkasan: Ini bukan kebetulan; _PyHASH_INF
hardcoded sebagai 314159 dalam implementasi CPython default Python, dan dipilih sebagai nilai arbitrer (jelas dari angka π) oleh Tim Peters pada tahun 2000 .
Nilai hash(float('inf'))
adalah salah satu parameter yang bergantung pada sistem dari fungsi hash bawaan untuk tipe numerik, dan juga tersedia seperti sys.hash_info.inf
pada 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
(Hasil yang sama dengan PyPy juga.)
Dalam hal kode, hash
adalah fungsi bawaan. Menyebutnya pada objek mengambang Python memanggil fungsi yang pointer diberikan oleh tp_hash
atribut tipe built-in mengambang ( PyTypeObject PyFloat_Type
), yang merupakan satu float_hash
fungsi, yang didefinisikan sebagai return _Py_HashDouble(v->ob_fval)
, yang pada gilirannya memiliki
if (Py_IS_INFINITY(v))
return v > 0 ? _PyHASH_INF : -_PyHASH_INF;
mana _PyHASH_INF
yang didefinisikan sebagai 314.159:
#define _PyHASH_INF 314159
Dalam hal sejarah, penyebutan pertama 314159
dalam konteks ini dalam kode Python (Anda dapat menemukan ini dengan git bisect
atau git log -S 314159 -p
) ditambahkan oleh Tim Peters pada Agustus 2000, dalam apa yang sekarang dilakukan 39dce293 dalam cpython
repositori git.
Pesan komit mengatakan:
Perbaiki untuk http://sourceforge.net/bugs/?func=detailbug&bug_id=111866&group_id=5470 . Ini adalah bug yang menyesatkan - "bug" yang sebenarnya adalah yang hash(x)
memberikan return error ketika x
infinity. Memperbaiki itu. Menambahkan Py_IS_INFINITY
makro baru ke
pyport.h
. Menata ulang kode untuk mengurangi duplikasi yang berkembang dalam hashing float dan angka kompleks, mendorong penusukan Trent sebelumnya pada kesimpulan logis. Memperbaiki bug yang sangat langka di mana hashing floats dapat mengembalikan -1 bahkan jika tidak ada kesalahan (tidak membuang waktu mencoba membangun kasus uji, itu hanya jelas dari kode yang dapat terjadi). Peningkatan hash kompleks sehingga
hash(complex(x, y))
tidak hash(complex(y, x))
lagi sama secara sistematis .
Secara khusus, dalam komit ini dia merobek kode static long float_hash(PyFloatObject *v)
in Objects/floatobject.c
dan membuatnya adil return _Py_HashDouble(v->ob_fval);
, dan dalam definisi long _Py_HashDouble(double v)
in Objects/object.c
dia menambahkan baris:
if (Py_IS_INFINITY(intpart))
/* can't convert to long int -- arbitrary */
v = v < 0 ? -271828.0 : 314159.0;
Jadi seperti yang disebutkan, itu adalah pilihan yang sewenang-wenang. Perhatikan bahwa 271828 terbentuk dari beberapa digit pertama desimal dari e .
Berkomitmen selanjutnya terkait:
hash(float('nan'))
menjadi0
.