Riepilogo: non è una coincidenza; _PyHASH_INF
è codificato come 314159 nell'implementazione CPython predefinita di Python, ed è stato scelto come valore arbitrario (ovviamente dalle cifre di π) da Tim Peters nel 2000 .
Il valore di hash(float('inf'))
è uno dei parametri dipendenti dal sistema della funzione hash integrata per i tipi numerici ed è disponibile anche come sys.hash_info.inf
in 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
(Stessi risultati anche con PyPy .)
In termini di codice, hash
è una funzione integrata. Chiamando su un oggetto galleggiante Python invoca la funzione cui puntatore è dato dalla tp_hash
attributo del tipo galleggiante incorporato ( PyTypeObject PyFloat_Type
), che è la float_hash
funzione, definita come return _Py_HashDouble(v->ob_fval)
, che a sua volta ha
if (Py_IS_INFINITY(v))
return v > 0 ? _PyHASH_INF : -_PyHASH_INF;
dove _PyHASH_INF
è definito come 314159:
#define _PyHASH_INF 314159
In termini di cronologia, la prima menzione 314159
in questo contesto nel codice Python (è possibile trovarlo con git bisect
o git log -S 314159 -p
) è stata aggiunta da Tim Peters nell'agosto 2000, in quello che ora è impegnato 39dce293 nel cpython
repository git.
Il messaggio di commit dice:
Correzione per http://sourceforge.net/bugs/?func=detailbug&bug_id=111866&group_id=5470 . Questo era un bug fuorviante - il vero "bug" era che hash(x)
restituiva un errore quando era x
un infinito. Risolto questo. Aggiunta nuova Py_IS_INFINITY
macro a
pyport.h
. Codice riorganizzato per ridurre la duplicazione crescente nell'hash di numeri mobili e complessi, spingendo la precedente pugnalata di Trent a una conclusione logica. Risolto bug estremamente raro in cui l'hashing dei float poteva restituire -1 anche se non ci fosse stato un errore (non perdere tempo nel tentativo di costruire un caso di test, era semplicemente ovvio dal codice che poteva accadere). Hash complesso migliorato in modo che
hash(complex(x, y))
non sia più sistematicamente uguale hash(complex(y, x))
.
In particolare, in questo commit ha strappato il codice di static long float_hash(PyFloatObject *v)
in Objects/floatobject.c
e lo ha reso giusto return _Py_HashDouble(v->ob_fval);
, e nella definizione di long _Py_HashDouble(double v)
in Objects/object.c
ha aggiunto le righe:
if (Py_IS_INFINITY(intpart))
/* can't convert to long int -- arbitrary */
v = v < 0 ? -271828.0 : 314159.0;
Quindi, come detto, è stata una scelta arbitraria. Si noti che 271828 è formato dalle prime cifre decimali di e .
Impegni correlati correlati:
hash(float('nan'))
essere0
.