Résumé: Ce n'est pas une coïncidence; _PyHASH_INF
est codé en dur comme 314159 dans l'implémentation CPython par défaut de Python, et a été choisi comme valeur arbitraire (évidemment à partir des chiffres de π) par Tim Peters en 2000 .
La valeur de hash(float('inf'))
est l'un des paramètres dépendants du système de la fonction de hachage intégrée pour les types numériques, et est également disponible comme sys.hash_info.inf
dans 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
(Même résultats avec PyPy aussi.)
En termes de code, hash
est une fonction intégrée. L'appeler sur un objet float Python appelle la fonction dont le pointeur est donné par l' tp_hash
attribut du type float intégré ( PyTypeObject PyFloat_Type
), qui est la float_hash
fonction, définie comme return _Py_HashDouble(v->ob_fval)
, qui à son tour a
if (Py_IS_INFINITY(v))
return v > 0 ? _PyHASH_INF : -_PyHASH_INF;
où _PyHASH_INF
est défini comme 314159:
#define _PyHASH_INF 314159
En termes d'histoire, la première mention 314159
dans ce contexte dans le code Python (vous pouvez le trouver avec git bisect
ou git log -S 314159 -p
) a été ajoutée par Tim Peters en août 2000, dans ce qui est maintenant commit 39dce293 dans le cpython
référentiel git.
Le message de validation dit:
Correctif pour http://sourceforge.net/bugs/?func=detailbug&bug_id=111866&group_id=5470 . C'était un bug trompeur - le vrai "bug" était celui qui hash(x)
renvoyait une erreur quand il x
était infini. Fixe ça. Ajout d'une nouvelle Py_IS_INFINITY
macro à
pyport.h
. Code réarrangé pour réduire la duplication croissante dans le hachage des nombres flottants et complexes, poussant Trent plus tôt à cela à une conclusion logique. Correction d'un bug extrêmement rare où le hachage des flottants pouvait retourner -1 même s'il n'y avait pas d'erreur (n'a pas perdu de temps à essayer de construire un cas de test, il était tout simplement évident d'après le code que cela pouvait arriver). Hachage complexe amélioré afin que ce
hash(complex(x, y))
ne soit plus systématiquement égal hash(complex(y, x))
.
En particulier, dans ce commit, il a arraché le code de static long float_hash(PyFloatObject *v)
in Objects/floatobject.c
et l'a rendu juste return _Py_HashDouble(v->ob_fval);
, et dans la définition de long _Py_HashDouble(double v)
in, Objects/object.c
il a ajouté les lignes:
if (Py_IS_INFINITY(intpart))
/* can't convert to long int -- arbitrary */
v = v < 0 ? -271828.0 : 314159.0;
Donc, comme mentionné, c'était un choix arbitraire. Notez que 271828 est formé à partir des premiers chiffres décimaux de e .
Commits ultérieurs associés:
hash(float('nan'))
qu'être0
.