Le hachage de l'infini dans Python a des chiffres correspondant pi :
>>> inf = float('inf')
>>> hash(inf)
314159
>>> int(math.pi*1e5)
314159
Est-ce juste une coïncidence ou est-ce intentionnel?
_PyHASH_INF
est défini comme une constante égal à 314159
.
Je ne trouve aucune discussion à ce sujet, ni aucun commentaire donnant une raison. Je pense qu'il a été choisi plus ou moins arbitrairement. J'imagine que tant qu'ils n'utilisent pas la même valeur significative pour d'autres hachages, cela ne devrait pas avoir d'importance.
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 20 .
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'attribut tp_hash
du type float intégré (PyTypeObject PyFloat_Type
), qui est la fonction float_hash
, 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 de 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 9dce29 dans le référentiel cpython
git.
Le message de validation dit:
Correction pour http://sourceforge.net/bugs/?func=detailbug&bug_id=111866&group_id=547 . C'était un bug trompeur - le vrai "bug" était que
hash(x)
renvoyait une erreur lorsquex
est un infini. Correction de ça. Ajout d'une nouvelle macroPy_IS_INFINITY
Àpyport.h
. Code réarrangé pour réduire la duplication croissante dans le hachage du flottant et des nombres 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 qu'il pourrait se produire). Hachage complexe amélioré afin quehash(complex(x, y))
ne soit plus systématiquement égal àhash(complex(y, x))
.
En particulier, dans ce commit, il a extrait le code de static long float_hash(PyFloatObject *v)
dans Objects/floatobject.c
Et l'a fait simplement return _Py_HashDouble(v->ob_fval);
, et dans la définition de long _Py_HashDouble(double v)
dans 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:
par Mark Dickinson en avril 201 ( aussi ), ce qui fait que le type Decimal
se comporte de la même manière
Par Mark Dickinson en avril 201 ( aussi ), déplacer cette vérification vers le haut et ajouter des cas de test
Par Mark Dickinson en mai 201 as numéro 8188 , réécriture complète de la fonction de hachage dans son implémentation actuelle , mais en conservant ce cas spécial, en donnant la constante un nom _PyHASH_INF
(en supprimant également le 271828, c'est pourquoi dans Python 3 hash(float('-inf'))
renvoie -314159
plutôt que -271828
comme il le fait dans Python 2)
Par Raymond Hettinger en janvier 2011 , en ajoutant un exemple explicite dans le "Quoi de neuf" pour Python 3.2 de sys.hash_info
Montrant la valeur ci-dessus. (Voir ici .)
Par Stefan Krah en mars 2012 modification du module Decimal mais conservation de ce hachage.
Par Christian Heimes en novembre 201 , a déplacé la définition de _PyHASH_INF
De Include/pyport.h
Vers Include/pyhash.h
Où il réside maintenant.
En effet,
sys.hash_info.inf
retour 314159
. La valeur n'est pas générée, elle est intégrée au code source. En réalité,
hash(float('-inf'))
retour -271828
, ou approximativement -e, dans python 2 ( c'est -314159 maintenant ).
Le fait que les deux nombres irrationnels les plus célèbres de tous les temps soient utilisés comme valeurs de hachage rend très peu probable une coïncidence.