Warum funktioniert die Python-hash der Unendlichkeit haben die Ziffern von π?
Den hash der Unendlichkeit in Python hat digits matching pi:
>>> inf = float('inf')
>>> hash(inf)
314159
>>> int(math.pi*1e5)
314159
Ist das nur Zufall oder ist es gewollt?
- Nicht sicher, aber meine Vermutung wäre, dass es als absichtlich, als
hash(float('nan'))
wird0
. - Hmm, keine Erwähnung darüber, dass in
sys.hash_info
. Easter egg? - Scheint, wie jemand in eine Frivole Stimmung eines Tages. Aber-warum nicht?
- Fragen Sie Tim Peters. Hier ist die commit-wo er eingeführt, diese Konstante, die vor 19 Jahren: github.com/python/cpython/commit/.... Ich behielt diese Besondere Werte, wenn ich überarbeitet der numerischen hash in bugs.python.org/issue8188
- Danke. Es sieht aus wie Tim kann auch verwendet die Ziffern von e für hash -inf ursprünglich.
- Ah ja, stimmt. Und anscheinend habe ich geändert, um
-314159
. Ich hatte vergessen, dass. - Wussten Sie testen diese in python-Implementierungen andere als CPython? PyPy, Jython? Wenn nicht, sollten Sie diesem tag mit der entsprechenden Laufzeit, wie es wahrscheinlich ist, spezifisch für die Umsetzung (ob absichtlich oder nicht).
- Ja, habe ich. Dieses Ergebnis ist dasselbe in CPython, PyPy und Jython.
- Bitte Bearbeiten Sie die Frage, weil die Antworten nicht erklären, warum andere Laufzeiten das gleiche zu tun.
- Der genaue Wert der hash nicht dokumentiert; die docs nur Zustand es ist gespeichert in
sys.hash_info.inf
, so ist es eindeutig nicht eine Sprache, die standard-und daher muss eine Implementierung detail. Diese Informationen haben sollten, kommen, um Licht in Ihre Forschung, was bedeutet, es gehört in die Frage. - Ich bin glücklich, mit der Frage in der aktuellen form, aber jeder hat Schreibrechte - wenn Sie denken, dass etwas fehlt (in der Frage oder den Antworten) nur gehen Sie vor und Bearbeiten.
Du musst angemeldet sein, um einen Kommentar abzugeben.
_PyHASH_INF
ist als Konstante definiert gleich314159
.Kann ich nicht finden, jede Diskussion über dieses oder Kommentare Angabe von Gründen. Ich denke, es wurde gewählt, mehr oder weniger willkürlich. Ich kann mir vorstellen, dass, solange Sie nicht die gleichen sinnvollen Wert für die anderen hashes, sollte es keine Rolle.
hash(314159)
ist auch314159
. Versuchen Sie auch, in Python 3,hash(2305843009214008110) == 314159
(dieser Eingang ist314159 + sys.hash_info.modulus
) etc.Fazit: Es ist kein Zufall;
_PyHASH_INF
ist fest als 314159 in der Standard CPython-Implementierung von Python, und wurde ausgewählt, als ein willkürlicher Wert (offensichtlich von der stellen von π) von Tim Peters im Jahr 2000.Den Wert
hash(float('inf'))
ist eine der system-dependent-Parameter der eingebaute hash-Funktion für numerische Typen, und ist auch verfügbar alssys.hash_info.inf
in Python 3:(Gleiche Ergebnisse mit PyPy zu.)
In Bezug auf code,
hash
ist eine integrierte Funktion. Berufung auf eine Python-float-Objekt, ruft die Funktion auf, deren Zeiger ist gegeben durch dietp_hash
- Attribut der built-in-Typ float (PyTypeObject PyFloat_Type
), die ist diefloat_hash
Funktion, definiert alsreturn _Py_HashDouble(v->ob_fval)
, die wiederum hatwo
_PyHASH_INF
ist definiert als 314159:In Bezug auf die Geschichte, die erste Erwähnung von
314159
in diesem Zusammenhang in der Python-code ein (Sie finden diese mitgit bisect
odergit log -S 314159 -p
) wurde Hinzugefügt von Tim Peters im August 2000, in dem, was ist jetzt Begehen 39dce293 in dercpython
git-repository.Die commit-Nachricht sagt:
Insbesondere In diesem Begehen, er Riss sich den code von
static long float_hash(PyFloatObject *v)
imObjects/floatobject.c
und machte es nurreturn _Py_HashDouble(v->ob_fval);
und in der definition vonlong _Py_HashDouble(double v)
imObjects/object.c
fügte er die Zeilen:Also wie erwähnt, es war eine willkürliche Wahl. Beachten Sie, dass 271828 wird gebildet aus den ersten paar Nachkommastellen von e.
Verwandte später begeht:
Von Mark Dickinson im Apr 2010 (auch), so dass die
Decimal
Art Verhalten sich ähnlich wieVon Mark Dickinson im Apr 2010 (auch), Umzug diese Prüfung an die Spitze und hinzufügen von test cases
Von Mark Dickinson im Mai 2010 als Problem 8188, komplett umschreiben die hash-Funktion deren aktuelle Umsetzung, aber Beibehaltung diesem speziellen Fall, geben Sie die Konstante ein name
_PyHASH_INF
(auch entfernen der 271828 das ist, warum in Python 3hash(float('-inf'))
zurück-314159
eher als-271828
wie in Python 2)Von Raymond Hettinger im Jan 2011, das hinzufügen einer expliziten Beispiel in der "Was ist neu" für Python 3.2
sys.hash_info
zeigt der obige Wert. (Siehe hier.)Von Stefan Krah in Mar 2012 ändern Sie den Decimal-Modul, sondern halten diesen hash.
Von Christian Heimes im Nov 2013, zog die definition von
_PyHASH_INF
ausInclude/pyport.h
zuInclude/pyhash.h
wo es jetzt lebt._Py_HashBytes(&v, sizeof(v))
?!? Also ich meine, in diesem speziellen Fall, Handhabung, Entnahme des Exponenten, etc. habe zu teuer sein - warum das Rad neu erfinden und die Gefahr ungleichmäßigen Auswirkungen der verschiedenen bits der Gleitkomma-Zahl?hash(42.0)
die gleichen sein wiehash(42)
auch das gleiche wiehash(Decimal(42))
undhash(complex(42))
undhash(Fraction(42, 1))
. Die Lösung (von Mark Dickinson) ist ein elegantes IMO: definieren einer mathematischen Funktion, die funktioniert für beliebige rationale Zahl, und mit der Tatsache, dass floating-point-zahlen sind die rationalen zahlen auch.hash(n) = n % M
wobei M = (2^61 - 1). Das ist verallgemeinert für rationale nhash(p/q) = (p/q) mod M
mit der division interpretiert wird modulo M (in anderen Worten:hash(p/q) = (p * inverse(q, M)) % M
). Der Grund, warum wir wollen, dass diese: wenn in einem dictd
wir setzend[x] = foo
und dann haben wirx==y
(z.B. 42.0==42) aberd[y]
ist nicht das gleiche wied[x]
, dann hätten wir ein problem. Die meisten der scheinbar komplexen code ergibt sich aus der Natur der floating-point-format selbst, um sich zu erholen die Fraktion richtig und in speziellen Fällen für inf und NaN-Werte.In der Tat,
zurück
314159
. Der Wert wird nicht generiert, es ist integriert in den source code.In der Tat,
zurück
-271828
oder rund -e, in python 2 (es ist -314159 jetzt).Die Tatsache, dass die beiden berühmtesten irrationalen zahlen aller Zeit verwendet werden, da die hash-Werte macht es sehr unwahrscheinlich, dass ein Zufall sein.