Ringkasan: Ini bukan kebetulan; _PyHASH_INFhardcoded 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.infpada 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, hashadalah fungsi bawaan. Menyebutnya pada objek mengambang Python memanggil fungsi yang pointer diberikan oleh tp_hashatribut tipe built-in mengambang ( PyTypeObject PyFloat_Type), yang merupakan satu float_hashfungsi, 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_INFyang didefinisikan sebagai 314.159:
#define _PyHASH_INF 314159
Dalam hal sejarah, penyebutan pertama 314159dalam konteks ini dalam kode Python (Anda dapat menemukan ini dengan git bisectatau git log -S 314159 -p) ditambahkan oleh Tim Peters pada Agustus 2000, dalam apa yang sekarang dilakukan 39dce293 dalam cpythonrepositori 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 xinfinity. Memperbaiki itu. Menambahkan Py_IS_INFINITYmakro 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.cdan membuatnya adil return _Py_HashDouble(v->ob_fval);, dan dalam definisi long _Py_HashDouble(double v)in Objects/object.cdia 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.