2011-10-04 8 views
11

मुझे समानता के लिए डेटा के बड़े हिस्से की तुलना करने की आवश्यकता है, और मुझे प्रति सेकंड, तेज़ की तुलना करने की आवश्यकता है। प्रत्येक वस्तु को एक ही आकार के लिए गारंटी दी जाती है, और यह संभव है/संभावना है कि वे केवल थोड़ा अलग हो (अज्ञात पदों में)।क्या यह पाइथन के अंतर्निर्मित हैश फ़ंक्शन का उचित उपयोग है?

मैंने नीचे इंटरैक्टिव सत्र से देखा है, == ऑपरेटर का उपयोग करके बाइट स्ट्रिंग्स धीमे हो सकते हैं यदि अंतर स्ट्रिंग के अंत की ओर हैं, और शुरुआत के दौरान कोई अंतर होने पर यह बहुत तेज़ हो सकता है।

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

हालांकि, मुझे इस हैश के कार्यान्वयन विवरण के बारे में कोई जानकारी नहीं है, क्या यह वास्तव में हैश की तरह है कि मैं आरामदायक हो सकता हूं कि hash(a) == hash(b) तब a == b बहुत संभावना है? मैं कुछ गलत परिणाम के लिए खुश हूँ, तो एक हैश टकराव (an array of 200 PS3s several hours to make a collision की आवश्यकता होगी, के अर्थ में दुर्लभ) यथोचित दुर्लभ है

In [1]: import hashlib 

In [2]: with open('/dev/urandom') as f: 
    ...:  spam = f.read(2**20 - 1) 
    ...:  

In [3]: spamA = spam + 'A' 

In [4]: Aspam = 'A' + spam 

In [5]: spamB = spam + 'B' 

In [6]: timeit spamA == spamB 
1000 loops, best of 3: 1.59 ms per loop 

In [7]: timeit spamA == Aspam 
10000000 loops, best of 3: 66.4 ns per loop 

In [8]: timeit hashlib.md5(spamA) == hashlib.md5(spamB) 
100 loops, best of 3: 4.42 ms per loop 

In [9]: timeit hashlib.md5(spamA) == hashlib.md5(Aspam) 
100 loops, best of 3: 4.39 ms per loop 

In [10]: timeit hash(spamA) == hash(spamB) 
10000000 loops, best of 3: 157 ns per loop 

In [11]: timeit hash(spamA) == hash(Aspam) 
10000000 loops, best of 3: 160 ns per loop 
+1

'हैश' फ़ंक्शन आर्किटेक्चर निर्भर है – JBernardo

उत्तर

25

पायथन के हैश फंक्शन गति के लिए डिज़ाइन किया गया है, और एक 64-बिट अंतरिक्ष में नक्शे। birthday paradox के कारण, इसका मतलब है कि आपको लगभग 5 बिलियन प्रविष्टियों पर टक्कर मिल जाएगी (शायद पहले से ही, क्योंकि हैश फ़ंक्शन क्रिप्टोग्राफ़िकल नहीं है)। इसके अलावा, hash की सटीक परिभाषा पायथन कार्यान्वयन पर निर्भर है, और वास्तुकला- या यहां तक ​​कि मशीन-विशिष्ट भी हो सकती है। इसका उपयोग न करें आप एकाधिक मशीनों पर एक ही परिणाम चाहते हैं।

md5 को क्रिप्टोग्राफिक हैश फ़ंक्शन के रूप में डिज़ाइन किया गया है; इनपुट में मामूली परेशानी भी आउटपुट को पूरी तरह बदल देती है। यह 128-बिट स्पेस में भी मैप करता है, जिससे यह संभव नहीं होता है कि आप कभी भी टक्कर का सामना करेंगे जबतक कि आप विशेष रूप से एक की तलाश नहीं कर रहे हैं।

यदि आप टक्कर को संभाल सकते हैं (यानी एक बाल्टी में सभी सदस्यों के बीच समानता के लिए परीक्षण, संभवतः एमडी 5 या एसएचए 2 जैसे क्रिप्टोग्राफिक एल्गोरिदम का उपयोग करके), पायथन का हैश फ़ंक्शन पूरी तरह से ठीक है।

एक और बात: अंतरिक्ष को बचाने के लिए, यदि आप इसे डिस्क पर लिखते हैं तो आपको डेटा को बाइनरी रूप में संग्रहीत करना चाहिए। (यानी struct.pack('!q', hash('abc'))/hashlib.md5('abc').digest())।

एक साइड नोट के रूप में: is पायथन में == के बराबर नहीं है। आपका मतलब == है।

+0

धन्यवाद, टक्कर हैंडलिंग मेरे लिए भी नहीं हुई थी .. आपके उत्तर ने मुझे' टाइमिट हैश (स्पैमए) == (स्पैमबी) और स्पैमए == स्पैमबी का उपयोग करने का विचार दिया है जिसने मुझे कार्यान्वयन के बारे में किसी भी चिंता के बारे में हैश माइनस का प्रदर्शन दिया। 'है' पर भी अच्छा पकड़, वह मेरे बारे में मैला था। – wim

+0

क्या यह '! Q' के बजाय'! Q' होना चाहिए? उदाहरण 'struct.pack ('! I ', हैश (' abc '))' मुझे 'struct.error देता है:' I 'प्रारूप को 0 <= संख्या <= 4294967295' की आवश्यकता होती है। –

+0

@ एंडीहेडन वास्तव में। फिक्स्ड। – phihag