क्यों अनंत के पायथन हैश's के अंक है?


241

पायथन में अनंत के हैश में अंक मिलान पाई है :

>>> inf = float('inf')
>>> hash(inf)
314159
>>> int(math.pi*1e5)
314159

क्या यह महज एक संयोग है या यह जानबूझकर किया गया है?


9
निश्चित नहीं है, लेकिन मेरा अनुमान है कि यह जानबूझकर किया hash(float('nan'))जा रहा है 0
CS95

1
हम्म, इस बारे में कोई उल्लेख नहीं है sys.hash_info। ईस्टर अंडा?
विम

123
टिम पीटर्स से पूछें। यहाँ वह जगह है जहाँ उन्होंने 19 साल पहले यह लगातार पेश किया था: github.com/python/cpython/commit/… । मैंने उन विशेष मानों को रखा, जब मैंने Bugs.python.org/issue8188
मार्क डिकिंसन

8
@MarkDickinson धन्यवाद। ऐसा लग रहा है कि टिम ने मूल रूप से हैश के लिए के अंकों का भी इस्तेमाल किया होगा ।
विम

17
@wim आह हाँ, सच। और जाहिर तौर पर मैंने इसे बदल दिया -314159। मैं उसके बारे में भूल गया था।
मार्क डिकिंसन

जवाबों:


47

_PyHASH_INFके बराबर एक स्थिर के रूप में परिभाषित किया गया है 314159

मुझे इस बारे में कोई चर्चा नहीं मिल रही है, या कोई कारण बताने वाली टिप्पणी नहीं मिल रही है। मुझे लगता है कि इसे कमोबेश मनमाने ढंग से चुना गया था। मुझे लगता है कि जब तक वे अन्य हैश के लिए समान सार्थक मूल्य का उपयोग नहीं करते हैं, तब तक कोई फर्क नहीं पड़ता।


6
लघु नाइटिक: परिभाषा के अनुसार यह लगभग अपरिहार्य है कि इसी मूल्य का उपयोग अन्य हैश के लिए किया जाएगा, जैसे कि इस मामले hash(314159)में भी 314159। इसके अलावा, पायथन 3 में प्रयास करें, hash(2305843009214008110) == 314159(यह इनपुट है 314159 + sys.hash_info.modulus) आदि
श्रीवत्सआर

3
@ श्रीवत्सआर मेरा मतलब सिर्फ यह था कि जब तक वे इस मान को परिभाषा द्वारा अन्य मूल्यों का हैश नहीं चुनते, तब तक इस तरह एक सार्थक मूल्य चुनने से हैश टकराव की संभावना नहीं बढ़ती
पैट्रिक हॉग

220

सारांश: यह एक संयोग नहीं है; पायथन के डिफ़ॉल्ट CPython कार्यान्वयन में _PyHASH_INF314159 के रूप में हार्डकोड किया गया है, और 2000 में टिम पीटर्स द्वारा एक मनमाना मूल्य (स्पष्ट रूप से π के अंकों से) के रूप में चुना गया था ।


hash(float('inf'))संख्यात्मक प्रकारों के लिए अंतर्निहित हैश फ़ंक्शन के सिस्टम-निर्भर मापदंडों में से एक का मान है, और पायथन 3 के रूप में भी उपलब्ध हैsys.hash_info.inf :

>>> 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

( PyPy के साथ भी समान परिणाम ।)


कोड के संदर्भ में, hashएक अंतर्निहित फ़ंक्शन है। एक अजगर नाव वस्तु पर यह कॉलिंग समारोह जिसका सूचक द्वारा दिया जाता है invokes tp_hashविशेषता में निर्मित नाव प्रकार (की PyTypeObject PyFloat_Type) है, जो हैfloat_hash समारोह, परिभाषित के रूप में return _Py_HashDouble(v->ob_fval), जो बारी में है

    if (Py_IS_INFINITY(v))
        return v > 0 ? _PyHASH_INF : -_PyHASH_INF;

जहां 314159 के रूप_PyHASH_INF में परिभाषित किया गया है:

#define _PyHASH_INF 314159

इतिहास के 314159संदर्भ में, पायथन कोड में इस संदर्भ में पहला उल्लेख (आप इस के साथ git bisectया पा सकते हैं git log -S 314159 -p) टिम पीटर्स द्वारा अगस्त 2000 में जोड़ा गया था , जो अब गिट रिपॉजिटरी में 39dce293 प्रतिबद्ध cpythonहै।

प्रतिबद्ध संदेश कहता है:

Http://sourceforge.net/bugs/?func=detailbug&bug_id=111866&group_id=5470 के लिए ठीक करें । यह एक भ्रामक बग था - सही "बग" यह था कि एक अनन्तता hash(x)होने पर एक त्रुटि वापसी दी गई थी x। तय किया कि में नया Py_IS_INFINITYमैक्रो जोड़ा गया pyport.h। फ्लोट और जटिल संख्या के हैशिंग में बढ़ते दोहराव को कम करने के लिए कोडित कोड, एक तार्किक निष्कर्ष पर ट्रेंट के पहले छुरा को धक्का देता है। बहुत हद तक दुर्लभ बग जहां फ्लोट्स के हैशिंग वापस आ सकते हैं, भले ही कोई त्रुटि न हो (परीक्षण के समय का निर्माण करने की कोशिश में समय बर्बाद न हो, यह कोड से बस स्पष्ट था कि ऐसा हो सकता है)। बेहतर जटिल हैश ताकि अब hash(complex(x, y))व्यवस्थित रूप से बराबर न हो hash(complex(y, x))

विशेष रूप से, इस में प्रतिबद्ध वह के कोड बाहर फट static long float_hash(PyFloatObject *v)में Objects/floatobject.cऔर यह सिर्फ बनाया return _Py_HashDouble(v->ob_fval);, और की परिभाषा में long _Py_HashDouble(double v)में Objects/object.cवह लाइनों कहा:

        if (Py_IS_INFINITY(intpart))
            /* can't convert to long int -- arbitrary */
            v = v < 0 ? -271828.0 : 314159.0;

जैसा कि उल्लेख किया गया है, यह एक मनमाना विकल्प था। ध्यान दें कि 271828 के पहले कुछ दशमलव अंकों से बनता है ।

संबंधित बाद में करता है:


44
-271828 के लिए चुनाव में-किसी भी संदेह को समाप्त करता है कि पीआई एसोसिएशन आकस्मिक था।
रसेल बोरोगोव

24
@RussellBorogove नहीं, लेकिन यह लगभग एक लाख गुना कम संभावना बनाता है;)
पाइप

8
@cmaster: उपरोक्त भाग देखें जहां यह मई 2010 कहते हैं, पर अर्थात् प्रलेखन अनुभाग संख्यात्मक प्रकार के हैशिंग और मुद्दा 8188 - विचार है कि हम चाहते है hash(42.0)के बराबर हो जाए hash(42), यह भी रूप में एक ही hash(Decimal(42))और hash(complex(42))और hash(Fraction(42, 1))। समाधान (मार्क डिकिन्सन द्वारा) एक सुरुचिपूर्ण एक आईएमओ है: एक गणितीय फ़ंक्शन को परिभाषित करना जो किसी भी तर्कसंगत संख्या के लिए काम करता है, और इस तथ्य का उपयोग करते हुए कि फ़्लोटिंग-पॉइंट संख्याएं तर्कसंगत संख्याएं भी हैं।
श्रीवत्सआर

1
@ श्रीवत्सआर आह, धन्यवाद। हालांकि मैंने इन समानताओं की गारंटी देने के लिए परवाह नहीं की होगी, यह जानना अच्छा है कि प्रतीत होता है कि जटिल कोड के लिए एक अच्छा, ठोस और तार्किक स्पष्टीकरण है :-)
cmaster - reicaate monica

2
@cmaster पूर्णांकों के लिए हैश फ़ंक्शन केवल hash(n) = n % MM = (2 ^ 61 - 1) है। यह तर्कसंगत n के लिए सामान्यीकृत है hash(p/q) = (p/q) mod Mजिसमें विभाजन की व्याख्या मोडुलो एम (दूसरे शब्दों में:) के साथ की गई है hash(p/q) = (p * inverse(q, M)) % M। इसका कारण हम यही चाहते हैं: यदि dहम एक तानाशाही में हैं d[x] = fooऔर तब हमारे पास x==y(जैसे 42.0 == 42) है, लेकिन d[y]जैसा है वैसा नहीं है d[x], तो हमें समस्या होगी। अधिकांश प्रतीत होता है जटिल कोड फ्लोटिंग-पॉइंट प्रारूप की प्रकृति से आता है, अंश को ठीक से पुनर्प्राप्त करने और inf और NaN मानों के लिए विशेष-मामलों की आवश्यकता के लिए।
श्रीवत्सआर

12

वास्तव में,

sys.hash_info.inf

लौटता है 314159। मान उत्पन्न नहीं हुआ है, यह स्रोत कोड में बनाया गया है। असल में,

hash(float('-inf'))

रिटर्न -271828, या लगभग-ई, अजगर 2 में ( यह अब -314159 है )।

तथ्य यह है कि सभी समय के दो सबसे प्रसिद्ध तर्कहीन संख्याओं का उपयोग हैश मूल्यों के रूप में किया जाता है, यह एक संयोग होने की संभावना को बहुत कम कर देता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.