हैश फ़ंक्शन को प्राइम नंबर मापांक का उपयोग क्यों करना चाहिए?


335

बहुत समय पहले, मैंने $ 1.25 के लिए सौदेबाजी की मेज से एक डेटा स्ट्रक्चर्स बुक खरीदी थी। इसमें हैशिंग फ़ंक्शन के लिए स्पष्टीकरण में कहा गया है कि इसे अंततः "गणित की प्रकृति" के कारण एक अभाज्य संख्या द्वारा मॉड करना चाहिए।

$ 1.25 पुस्तक से आप क्या उम्मीद करते हैं?

वैसे भी, मेरे पास गणित की प्रकृति के बारे में सोचने के लिए कई साल हैं, और फिर भी मैं इसका पता नहीं लगा सकता।

क्या संख्याओं का वितरण सही मायने में तब भी है जब बाल्टियों की संख्या कम है? या यह है कि हर कोई स्वीकार करता है क्योंकि हर एक पुराने प्रोग्रामर की कहानी है किसी और उसे स्वीकार कर लेगा?


1
पूरी तरह से उचित सवाल: बाल्टी की एक प्रमुख संख्या क्यों होनी चाहिए?
ड्रेमन जूल

1
यह प्रश्न ऑफ़-टॉपिक प्रतीत होता है क्योंकि यह संभावना से अधिक कंप्यूटर साइंस पर है
ऑर्बिट

2
cs.stackexchange.com/a/64191/64222 एक और अच्छी तरह से तर्क दिया विवरण।
ग्रीन ट्री


यहाँ कुछ चौंकाने बारीक संख्या के साथ कुछ हद तक एक संबंधित सवाल के लिए एक और महान व्याख्या दी गई है - quora.com/...
AnBisw

जवाबों:


242

आमतौर पर एक साधारण हैश फ़ंक्शन इनपुट के "घटक भागों" (एक स्ट्रिंग के मामले में वर्ण) को ले कर काम करता है, और उन्हें कुछ स्थिरांक की शक्तियों से गुणा करता है, और उन्हें कुछ पूर्णांक प्रकार में एक साथ जोड़ता है। उदाहरण के लिए एक विशिष्ट (हालांकि विशेष रूप से अच्छा नहीं) एक स्ट्रिंग का हैश हो सकता है:

(first char) + k * (second char) + k^2 * (third char) + ...

फिर यदि सभी पहले समान चार वाले तार का एक गुच्छा खिलाया जाता है, तो परिणाम सभी एक ही modulo k होंगे, कम से कम जब तक पूर्णांक प्रकार के ओवरफ्लो नहीं होंगे।

[एक उदाहरण के रूप में, जावा का स्ट्रिंग हैशकोड इसी के समान है - यह वर्णों को उल्टा क्रम देता है, k = 31 के साथ। तो आप स्ट्राइक रिलेशनशिप मोडुलो 31 को स्ट्रिंग्स के बीच में ले जाते हैं जो उसी तरह से समाप्त होते हैं, और स्ट्राइकिंग रिलेशनशिप मोडुलो 2 ^ 32 स्ट्रिंग्स के बीच जो अंत के पास के समान हैं। यह हैशटेबल व्यवहार को गंभीर रूप से गड़बड़ नहीं करता है।]

एक हैशटेबल हैश के मापांक को बाल्टियों की संख्या पर ले जाकर काम करता है।

यह हैशटेबल में महत्वपूर्ण है कि संभावित मामलों के लिए टक्कर का उत्पादन न करें, क्योंकि टक्कर हैशटेबल की दक्षता को कम करती है।

अब, मान लीजिए कि किसी ने मानों की एक पूरी गुच्छा एक हैशटेबल में डाल दिया है, जो वस्तुओं के बीच कुछ संबंध रखता है, जैसे कि सभी का पहला चरित्र है। यह एक काफी अनुमानित पूर्वानुमान पैटर्न है, मैं कहूंगा, इसलिए हम नहीं चाहते कि यह बहुत अधिक टकराव पैदा करे।

यह पता चला है कि "गणित की प्रकृति के कारण", यदि हैश में निरंतर उपयोग किया जाता है, और बाल्टियों की संख्या मैथुन होती है , तो कुछ सामान्य मामलों में टकराव को कम किया जाता है। यदि वे नकल नहीं कर रहे हैं, तो इनपुट के बीच कुछ काफी सरल संबंध हैं जिनके लिए टकराव को कम नहीं किया जाता है। सभी हैश समान कारक के समान निकलते हैं, जिसका अर्थ है कि वे सभी बाल्टी के 1 / n वें भाग में गिरेंगे जिसका सामान्य कारक है। आपको कई बार टकराव के रूप में n मिलता है, जहां n सामान्य कारक है। चूंकि n कम से कम 2 है, मैं कहूंगा कि यह सामान्य उपयोग के मामले में कम से कम दो बार सामान्य रूप से कई टकराव उत्पन्न करने के लिए अस्वीकार्य है। यदि कुछ उपयोगकर्ता बाल्टी में हमारे वितरण को तोड़ने जा रहे हैं, तो हम चाहते हैं कि यह एक अजीब दुर्घटना हो, न कि कुछ सरल पूर्वानुमान।

अब, हैशटेबल कार्यान्वयन स्पष्ट रूप से उन पर लगाए गए वस्तुओं पर कोई नियंत्रण नहीं है। वे उन्हें संबंधित होने से नहीं रोक सकते। तो यह सुनिश्चित करने के लिए बात यह है कि स्थिर और बाल्टी मायने रखती है सहानुभूति। इस तरह आप कुछ छोटे सामान्य कारक के संबंध में बाल्टी के मापांक को निर्धारित करने के लिए अकेले "अंतिम" घटक पर भरोसा नहीं कर रहे हैं। जहां तक ​​मुझे पता है कि उन्हें यह हासिल करने के लिए प्राइम होने की जरूरत नहीं है, बस कोप्राइम।

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

व्यवहार में, मुझे लगता है कि बाल्टी की संख्या के रूप में 2 की शक्ति का उपयोग करना काफी सामान्य है। यह सुविधाजनक है और सही परिमाण की एक प्रमुख संख्या के आसपास खोज करने या पूर्व-चयन करने से बचाता है। तो आप हैश फंक्शन पर भी मल्टीप्लायरों का उपयोग नहीं करने का भरोसा करते हैं, जो आमतौर पर एक सुरक्षित धारणा है। लेकिन आप अभी भी सामयिक बुरे हैशिंग व्यवहारों को ऊपर दिए गए हैश कार्यों के आधार पर प्राप्त कर सकते हैं, और प्राइम बकेट काउंट आगे मदद कर सकते हैं।

इस सिद्धांत के बारे में कहना कि "सब कुछ प्रधान होना है" जहां तक ​​मैं जानता हूं कि एक पर्याप्त है, लेकिन शत्रुओं पर अच्छे वितरण के लिए एक आवश्यक शर्त नहीं है। यह सभी को यह मानने की आवश्यकता के बिना हस्तक्षेप करने की अनुमति देता है कि दूसरों ने एक ही नियम का पालन किया है।

[संपादित करें: एक बड़ी संख्या में बाल्टी का उपयोग करने का एक और विशेष कारण है, जो कि यदि आप रैखिक जांच के साथ टकराव को संभालते हैं। फिर आप हैशकोड से एक स्ट्राइड की गणना करते हैं, और यदि वह स्ट्राइड बकेट काउंट का एक कारक बन जाता है तो आप केवल उसी समय (बकेट_काउंट / स्ट्राइड) जांच कर सकते हैं जब आप शुरू कर चुके हैं। जिस मामले से आप सबसे बचना चाहते हैं, वह है = 0, निश्चित रूप से, जो विशेष आवरण वाला होना चाहिए, लेकिन विशेष आवरण वाली बाल्टी से बचने के लिए / एक छोटे पूर्णांक के बराबर स्ट्राइड, आप सिर्फ बाल्टी को बना सकते हैं। स्ट्राइड प्रदान किया जाता है यह 0. नहीं है।]


बस एक साइड नोट के रूप में:
हैशकोड

9
यह एक शानदार जवाब है। क्या आप इसे आगे समझा सकते हैं "तो आप स्ट्राइकिंग रिलेशनशिप मोडुलो 31 को स्ट्रिंग्स के बीच में ले आते हैं जो उसी तरह से समाप्त होते हैं, और स्ट्राइकिंग रिलेशनशिप मोडुलो 2 ^ 32 स्ट्रिंग्स के बीच में जो अंत के पास के समान हैं। यह हैशटेब बिहेवियर को गंभीर रूप से गड़बड़ नहीं करता है। " मैं विशेष रूप से 2 ^ 32 भाग को नहीं समझता
साधारण

2
इस बारे में चीजों को और अधिक स्पष्ट करने के लिए अतिरिक्त ध्यान दें: "सभी हैश आम कारक समान रूप से सामने आते हैं" -> ऐसा इसलिए है, क्योंकि यदि आप उदाहरण हैश फ़ंक्शन हैश = 1 char + 2nd char * k + ..., और एक ही पहले वर्ण के साथ तार लें, इन तार के लिए हैश% k समान होगा। यदि M, हैशटेबल का आकार है और g, M और k का gcd है, तो (हैश% k)% g, हैश% g (g से k को विभाजित करता है) के बराबर है और इसलिए हैश% g आपके स्ट्रिंग्स के लिए भी समान होगा। अब विचार करें (हैश% एम)% जी, यह हैश% जी (जी विभाजन एम के बाद से) के बराबर है। तो (हैश% M)% g इन सभी स्ट्रिंग्स के लिए बराबर है।
क्वार्क

1
@DanielMcLaury जोशुआ बलोच ने बताया कि जावा के लिए क्यों - दो लोकप्रिय पुस्तकों (K & R, ड्रैगन बुक) में इसकी सिफारिश की गई और अंग्रेजी शब्दकोश में कम टकराव के साथ अच्छा प्रदर्शन किया। यह तेज़ है ( हॉर्नर की विधि का उपयोग करता है )। जाहिर है यहां तक ​​कि कश्मीर और आर याद नहीं है कि यह कहाँ से आया है। इसी तरह के समारोह में राबिन -कार्प एल्गोरिथ्म (1981) से राबिन फिंगरप्रिंट है , लेकिन केएंडआर (1978) पूर्ववर्ती है।
बैन

1
@SteveJessop, क्या आप "स्ट्राइकिंग रिलेशनशिप्स मोडुलो 2 ^ 32 को स्ट्रिंग्स के बीच समझा सकते हैं जो अंत के पास समान हैं।" धन्यवाद।
खन्ना ११

29

हैश टेबल से इंसर्टिंग / रीट्रेसिंग करते समय सबसे पहला काम यह होता है कि दिए गए की के लिए हैशकोड की गणना करें और फिर हैशटैड के आकार को हैशकोड को ट्रिब्यूट करके सही बकेट का पता लगाएं, हैशटैड% table_length करके। यहाँ 2 'कथन' हैं जिन्हें आपने शायद कहीं पढ़ा है

  1. यदि आप table_length के लिए 2 की शक्ति का उपयोग करते हैं, तो खोज (हैशकोड (कुंजी)% 2 ^ n) के रूप में सरल और त्वरित है (हैशकोड (कुंजी) और (2 ^ n -1))। लेकिन अगर किसी दिए गए कुंजी के लिए हैशकोड की गणना करने का आपका कार्य अच्छा नहीं है, तो आप निश्चित रूप से कुछ हैश बाल्टी में कई कुंजी के क्लस्टरिंग से पीड़ित होंगे।
  2. लेकिन अगर आप table_length के लिए प्राइम नंबर का उपयोग करते हैं, तो हैशकोड की गणना अलग-अलग हैश बकेट में मैप कर सकती है, भले ही आपके पास थोड़ा बेवकूफ हैशकोड फ़ंक्शन हो।

और यहाँ प्रमाण है।

यदि मान लें कि आपके हैशकोड फ़ंक्शन का परिणाम अन्य, {x, 2x, 3x, 4x, 5x, 6x ...} के बीच हैशकोड में है, तो ये सभी सिर्फ मीटर की बाल्टी में क्लस्टर किए जा रहे हैं, जहां = table_length / GreatestCommonFactor (table_length, x)। (इसे सत्यापित / प्राप्त करना तुच्छ है)। अब आप क्लस्टरिंग से बचने के लिए निम्न में से एक कर सकते हैं

सुनिश्चित करें कि आप बहुत अधिक हैशकोड उत्पन्न नहीं करते हैं जो {x, 2x, 3x, 4x, 5x, 6x ...} जैसे किसी अन्य हैशकोड के गुणक हैं। लेकिन यदि आपके हैशटेबल को माना जाता है तो यह एक तरह का मुश्किल हो सकता है। लाखों प्रविष्टियाँ। या केवल x_ के साथ table_length कोप्राइम बनाकर, GreatestCommonFactor (table_length, x) को 1 के बराबर करके table_length के बराबर करें। और अगर x किसी संख्या के बारे में हो सकता है, तो सुनिश्चित करें कि table_length एक प्रमुख संख्या है।

से - http://srinvis.blogspot.com/2006/07/hash-table-lengths-and-prime-nn.html


11

http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/

चित्रों के साथ भी बहुत स्पष्ट व्याख्या।

संपादित करें: सारांश के रूप में, primes का उपयोग किया जाता है क्योंकि आपके पास चुने गए अभाज्य संख्या द्वारा मूल्यों को गुणा करने और उन्हें सभी को जोड़ने पर एक अद्वितीय मूल्य प्राप्त करने का सबसे अच्छा मौका है। उदाहरण के लिए एक स्ट्रिंग दी गई है, प्रत्येक अक्षर मान को अभाज्य संख्या से गुणा करना और फिर उन सभी को जोड़ना आपको इसका हैश मान देगा।

एक बेहतर सवाल यह होगा कि 31 नंबर क्यों?


5
हालाँकि, मुझे लगता है कि एक सारांश उपयोगी होगा, अगर वह साइट कभी मृत हो जाती है, तो एसओ पर इसकी सामग्री के कुछ अवशेष यहां सहेजे जाएंगे।
थॉमस ओवेन्स

2
लेख क्यों नहीं समझाता है, लेकिन कहते हैं "शोधकर्ताओं ने पाया कि 31 के प्राइम का उपयोग करने से चाबियों का बेहतर वितरण होता है, और टक्करों की संख्या कम होती है। कोई नहीं जानता कि क्यों ..." मजेदार, एक ही सवाल पूछ रहा है जो मुझे प्रभाव में है ।
theschmitzer

> एक बेहतर सवाल यह होगा कि 31 नंबर क्यों? यदि आप मतलब है कि संख्या 31 का उपयोग क्यों किया जाता है, तो आप जिस लेख को इंगित करते हैं, वह आपको बताता है कि क्यों, क्योंकि यह कई से जल्दी है और कॉस परीक्षणों से पता चलता है कि यह उपयोग करने के लिए सबसे अच्छा है। मैंने जो दूसरा लोकप्रिय गुणक देखा है, वह 33 है जो इस सिद्धांत को वजन देता है कि गति का मुद्दा (कम से कम शुरू में) एक महत्वपूर्ण कारक था। अगर आपका मतलब है, यह 31 के बारे में क्या है जो परीक्षणों में इसे बेहतर बनाता है, तो मुझे डर है कि मुझे पता नहीं है।
जुम्मे की रात

वास्तव में, एक ही कारण है कि यह एक गुणक के रूप में इस्तेमाल किया जा सकता था क्योंकि यह गुणा द्वारा आसान था। (जब मैं कहता हूं कि मैंने 33 को एक गुणक के रूप में उपयोग किया है, तो मेरा मतलब यह नहीं है कि हाल ही में, यह दशकों पहले था, और हैशिंग पर बहुत विश्लेषण किए जाने से पहले संभव था।)
सग्मोर जुले

3
@SteveJessop 31 नंबर एक (एक्स * 32) -1 ऑपरेशन के रूप में सीपीयू द्वारा आसानी से अनुकूलित किया जाता है, जिसमें *32एक साधारण बिट शिफ्ट, या इससे भी बेहतर तत्काल पता स्केल फैक्टर होता है (जैसे lea eax,eax*8; leax, eax,eax*4x86 / x64 पर)। तो *31प्राइम नंबर गुणा के लिए एक अच्छा उम्मीदवार है। यह कुछ साल पहले बहुत ज्यादा सच था - अब नवीनतम सीपीयू वास्तुकला में लगभग तुरंत गुणा है - विभाजन हमेशा धीमा होता है ...
अरनौद बुचेज़

10

tl; डॉ

index[hash(input)%2]सभी संभावित हैश के आधे और मूल्यों की एक श्रृंखला के लिए टक्कर होगी। index[hash(input)%prime]सभी संभावित हैश की <2 की टक्कर में परिणाम। तालिका आकार में विभाजक को ठीक करने से यह भी सुनिश्चित होता है कि संख्या तालिका से अधिक नहीं हो सकती है।


1
2 एक प्रमुख संख्या है यार
गणेश चौधरी सदनला

8

प्राइम्स का उपयोग किया जाता है क्योंकि आपके पास एक विशिष्ट हैश-फ़ंक्शन के लिए एक अद्वितीय मूल्य प्राप्त करने की अच्छी संभावना है जो कि पॉलिनॉमिअल्स मोडुलो पी। कहते हैं, आप लंबाई के तारों के लिए ऐसे हैश-फ़ंक्शन का उपयोग करते हैं <= N, और आपके पास एक टक्कर है। इसका मतलब है कि 2 अलग-अलग बहुपद एक ही मूल्य के modulo P का उत्पादन करते हैं। उन बहुपद का अंतर फिर से उसी डिग्री N (या उससे कम) का बहुपद है। इसकी एन रूट्स से अधिक नहीं है (यह यहां गणित की प्रकृति ही बताती है, क्योंकि यह दावा केवल एक क्षेत्र = बहु संख्या में बहुपद के लिए सही है)। इसलिए यदि N, P से बहुत कम है, तो आपको टक्कर नहीं होने की संभावना है। उसके बाद, प्रयोग संभवतः दिखा सकता है कि स्ट्रिंग्स के हैश-टेबल के लिए टकराव से बचने के लिए 37 काफी बड़ा है, जिसकी लंबाई 5-10 है, और गणना के लिए उपयोग करने के लिए पर्याप्त छोटा है।


1
जबकि स्पष्टीकरण अब स्पष्ट लगता है, यह ए.शेन द्वारा एक पुस्तक पढ़ने के बाद मुझे मिला "प्रोग्रामिंग: सिद्धांत और समस्याएं" (रूसी में), राबिन एल्गोरिथ्म की चर्चा देखें। यकीन नहीं होता कि एक अंग्रेजी अनुवाद मौजूद है।
TT_

5

बस एक वैकल्पिक दृष्टिकोण प्रदान करने के लिए यह साइट है:

http://www.codexon.com/posts/hash-functions-the-modulo-prime-myth

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


बाल्टी की बड़ी संख्या का मतलब कम टकराव है: कबूतर का सिद्धांत देखें।
अज्ञात

11
@ परिचित: मेरा मानना ​​है कि यह सच नहीं है। कृपया मुझे सही करें अगर मैं गलत हूं, लेकिन मेरा मानना ​​है कि कबूतरों के सिद्धांत को हैश टेबल पर लागू करना केवल आपको यह दावा करने की अनुमति देता है कि क्या टक्कर होगी यदि आपके पास डिब्बे की तुलना में अधिक तत्व हैं, तो टकराव की मात्रा या घनत्व पर कोई निष्कर्ष निकालने के लिए नहीं। मैं अब भी मानता हूं कि बड़ी संख्या में डिब्बे सही मार्ग हैं, हालांकि।
फालना

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

1
@ ज्ञात है कि आप चूक गए हैं कि टक्कर भी हैश फ़ंक्शन पर निर्भर करती है। तो अगर फंक्शन वास्तव में खराब है, तो कोई फर्क नहीं पड़ता कि आप कितने बड़े आकार में वृद्धि करते हैं, फिर भी टकराव की महत्वपूर्ण मात्रा हो सकती है
सूरज चंद्रन

मूल लेख चला गया लगता है, लेकिन यहाँ कुछ असंवेदनशील टिप्पणियाँ हैं, जिसमें मूल लेखक के साथ एक चर्चा भी शामिल है। news.ycombinator.com/item?id=650487
एड्रियन मैककार्थी

3

प्राइम्स यूनिक नंबर होते हैं। वे उस में अद्वितीय हैं, किसी भी अन्य संख्या के साथ प्राइम के उत्पाद को इस तथ्य के कारण अद्वितीय होने का सबसे अच्छा मौका है (स्वयं के प्रमुख के रूप में अनूठा नहीं है) इस तथ्य के कारण कि एक प्राइम को बनाने के लिए उपयोग किया जाता है। इस संपत्ति का उपयोग हैशिंग कार्यों में किया जाता है।

एक स्ट्रिंग "सैमुअल" को देखते हुए, आप प्रत्येक घटक के अंकों या अक्षरों को प्राइम संख्या के साथ गुणा करके और उन्हें जोड़कर एक अद्वितीय हैश उत्पन्न कर सकते हैं। यही कारण है कि primes का उपयोग किया जाता है।

हालाँकि primes का उपयोग करना एक पुरानी तकनीक है। यहां यह समझने की कुंजी है कि जब तक आप एक पर्याप्त अनूठी कुंजी उत्पन्न कर सकते हैं तब तक आप अन्य हैशिंग तकनीकों में भी स्थानांतरित कर सकते हैं। इस विषय पर अधिक जानकारी के लिए यहां जाएं http://www.azillionmonkeys.com/qed/hash.html

http://computinglife.wordpress.com/2008/11/20/why-do-hash-functions-use-prime-numbers/


1
हाहाहा .... वास्तव में 2 प्राइम के उत्पाद में प्राइम और किसी अन्य नंबर के उत्पाद की तुलना में 'अद्वितीय' होने का एक बेहतर मौका नहीं है?
हसनीह

@Beska यहाँ "विशिष्टता" को पुनरावर्ती रूप से परिभाषित किया गया है, इसलिए मेरा मानना ​​है कि "गैर-विशिष्टता" को उसी तरह से परिभाषित किया जाना चाहिए :)
TT_

3

यह हैश फ़ंक्शन की पसंद पर निर्भर करता है।

कई हैश फ़ंक्शन डेटा में विभिन्न तत्वों को कुछ कारकों के साथ गुणा करके जोड़ते हैं, जो मशीन के शब्द आकार के अनुरूप दो की शक्ति को मापता है (जो मापांक को केवल अतिप्रवाह से मुक्त करके मापांक मुक्त होता है)।

आप डेटा तत्व और हैश तालिका के आकार के लिए गुणक के बीच कोई सामान्य कारक नहीं चाहते हैं, क्योंकि तब यह हो सकता है कि डेटा तत्व को अलग करने से डेटा पूरी तालिका में फैल न जाए। यदि आप तालिका के आकार के लिए एक प्रमुख चुनते हैं तो ऐसा सामान्य कारक अत्यधिक संभावना नहीं है।

दूसरी ओर, वे कारक आमतौर पर विषम अपराधों से बने होते हैं, इसलिए आपको अपनी हैश टेबल के लिए दो की शक्तियों का उपयोग करके भी सुरक्षित होना चाहिए (जैसे कि जब यह जावा हैशकोड () विधि उत्पन्न करता है तो ग्रहण 31 का उपयोग करता है)।


2

मान लीजिए कि आपका टेबल-आकार (या मोडुलो के लिए नंबर) T = (B * C) है। अब यदि आपके इनपुट के लिए हैश है (N * A * B) की तरह जहां N कोई पूर्णांक हो सकता है, तो आपका आउटपुट अच्छी तरह से वितरित नहीं होगा। क्योंकि हर बार n C, 2C, 3C इत्यादि हो जाता है, आपका आउटपुट दोहराना शुरू कर देगा। यानी आपका आउटपुट केवल C पदों पर वितरित किया जाएगा। ध्यान दें कि C यहाँ है (T / HCF (टेबल-आकार, हैश))।

एचसीएफ बनाकर इस समस्या को खत्म किया जा सकता है। 1. इसके लिए प्राइम नंबर बहुत अच्छे हैं।

एक और दिलचस्प बात है जब टी 2 ^ एन है। ये इनपुट-हैश के सभी निचले एन बिट्स के समान आउटपुट देंगे। जैसा कि हर संख्या में 2 की शक्तियों का प्रतिनिधित्व किया जा सकता है, जब हम T के साथ किसी भी संख्या का मोडुलो लेंगे, हम 2 फॉर्म नंबर की सभी शक्तियों को घटा देंगे, जो कि> = N हैं, इसलिए हमेशा इनपुट पर निर्भर विशिष्ट पैटर्न की संख्या देना । यह भी एक बुरा विकल्प है।

इसी तरह, टी 10 ^ एन समान कारणों से खराब है (बाइनरी के बजाय संख्याओं के दशमलव संकेतन में पैटर्न)।

तो, प्राइम नंबर एक बेहतर वितरित परिणाम देते हैं, इसलिए तालिका आकार के लिए अच्छे विकल्प हैं।


2

मेरे अन्य उत्तर https://stackoverflow.com/a/43126969/917428 से कॉपी करना । अधिक विवरण और उदाहरणों के लिए इसे देखें।

मेरा मानना ​​है कि यह सिर्फ इस तथ्य के साथ करना है कि कंप्यूटर बेस 2 में काम करते हैं। बस यह सोचें कि आधार 10 के लिए समान काम कैसे करता है:

  • 8% 10 = 8
  • 18% 10 = 8
  • 87865378% 10 = 8

इससे कोई फर्क नहीं पड़ता कि संख्या क्या है: जब तक यह 8 के साथ समाप्त होता है, तब तक इसका modulo 10 8 होगा।

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


1

मैं स्टीव जेसप के जवाब के लिए कुछ जोड़ना चाहूंगा (मैं उस पर टिप्पणी नहीं कर सकता क्योंकि मेरे पास पर्याप्त प्रतिष्ठा नहीं है)। लेकिन मुझे कुछ सहायक सामग्री मिली। उनका जवाब बहुत मदद करता है लेकिन उन्होंने एक गलती की: बाल्टी का आकार 2. की शक्ति नहीं होना चाहिए। मैं थॉमस कॉर्मेन, चार्ल्स लीसेनसन, एट अल द्वारा पेज 263 पर किताब "इंट्रोडक्शन टू अल्गोरिदम" का उद्धरण दूंगा:

विभाजन पद्धति का उपयोग करते समय, हम आमतौर पर मी के कुछ मूल्यों से बचते हैं। उदाहरण के लिए, m को 2 की शक्ति नहीं होनी चाहिए, क्योंकि यदि m = 2 ^ p है, तो h (k) k का p निम्नतम-क्रम बिट्स है। जब तक हम नहीं जानते कि सभी कम-ऑर्डर पी-बिट पैटर्न समान रूप से होने की संभावना है, हम कुंजी के सभी बिट्स पर निर्भर करने के लिए हैश फ़ंक्शन को डिज़ाइन करना बेहतर है। जैसा कि एक्सरसाइज 11.3-3 आपको दिखाने के लिए कहता है, जब m = 2 ^ p-1 का चयन करना होता है जब k एक मूलांक 2 में व्याख्यायित स्ट्रिंग होता है, तो p एक खराब विकल्प हो सकता है, क्योंकि k के वर्णों की अनुमति देने से इसका हैश मान नहीं बदलता है।

आशा है ये मदद करेगा।


0

एक हैश फंक्शन के लिए, यह न केवल आम तौर पर विभाजन को कम करने के लिए महत्वपूर्ण है, बल्कि कुछ बाइट्स का जप करते हुए उसी हैश के साथ रहना असंभव है।

कहते हैं कि आपके पास एक समीकरण है: (x + y*z) % key = xसाथ 0<x<keyऔर 0<z<key। यदि कुंजी एक primenumber n * y = key है तो N के प्रत्येक n के लिए सही है और हर दूसरी संख्या के लिए गलत है।

एक उदाहरण जहां कुंजी एक प्रमुख उदाहरण नहीं है: x = 1, z = 2 और key = 8 क्योंकि कुंजी / z = 4 अभी भी एक प्राकृतिक संख्या है, 4 हमारे समीकरण के लिए एक समाधान बन जाता है और इस मामले में (n / 2) * y = कुंजी N में प्रत्येक n के लिए सही है। समीकरण के लिए समाधानों की मात्रा व्यावहारिक रूप से दोगुनी हो गई है क्योंकि 8 एक प्रमुख नहीं है।

यदि हमारे हमलावर को पहले से ही पता है कि समीकरण के लिए 8 संभव समाधान है, तो वह फ़ाइल को 8 से 4 के उत्पादन से बदल सकता है और अभी भी वही हैश प्राप्त कर सकता है।


0

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

आप लेख में सभी विवरण यहाँ पा सकते हैं , लेकिन मान लें कि निम्नलिखित सही हैं:

  • प्राइम नंबर का उपयोग करने से हमें एक अद्वितीय मूल्य का "सर्वोत्तम मौका" मिलता है

एक सामान्य हैशमप कार्यान्वयन 2 चीजों को अद्वितीय बनाना चाहता है।

  • कुंजी के लिए अद्वितीय हैश कोड
  • वास्तविक मूल्य को संग्रहीत करने के लिए अद्वितीय सूचकांक

हमें यूनिक इंडेक्स कैसे मिलता है? आंतरिक कंटेनर के प्रारंभिक आकार को एक प्रमुख बनाकर। इसलिए मूल रूप से, प्राइम शामिल है क्योंकि इसमें अद्वितीय संख्याओं के उत्पादन का यह अनूठा गुण है जो हम आईडी वस्तुओं का उपयोग करते हुए और आंतरिक कंटेनर के अंदर अनुक्रमित ढूंढते हुए समाप्त करते हैं।

उदाहरण:

कुंजी = "कुंजी"

मान = "मान" uniqueId = "k" * 31 ^ 2 + "e" * 31 ^ 1` + "y"

अद्वितीय आईडी के लिए नक्शे

अब हम अपने मूल्य के लिए एक विशिष्ट स्थान चाहते हैं - इसलिए हम

uniqueId % internalContainerSize == uniqueLocationForValueमान internalContainerSizeलेना भी एक प्रमुख है।

मुझे पता है कि यह सरल है, लेकिन मैं सामान्य विचार के माध्यम से प्राप्त करने की उम्मीद कर रहा हूं।


0

प्राइम पावर मोडुली के बारे में "गणित की प्रकृति" यह है कि वे एक परिमित क्षेत्र के निर्माण खंड हैं । अन्य दो बिल्डिंग ब्लॉक एक जोड़ और गुणा ऑपरेशन हैं। प्राइम मोडुली की विशेष संपत्ति यह है कि वे "नियमित" जोड़ और गुणा संचालन के साथ एक परिमित क्षेत्र बनाते हैं, बस मापांक में ले जाया जाता है। इसका मतलब यह है कि प्रत्येक गुणन मानचित्र एक भिन्न पूर्णांक मापांक को अभाज्य बनाता है, इसलिए हर जोड़ को जोड़ता है।

प्राइम मोडुली फायदेमंद हैं क्योंकि:

  • वे सबसे अधिक स्वतंत्रता देते हैं जब माध्यमिक हैशिंग में माध्यमिक गुणक का चयन करते हैं, 0 को छोड़कर सभी गुणक सभी तत्वों को एक ही बार में समाप्त कर देंगे
  • यदि सभी हैश मापांक से कम हैं, तो कोई टक्कर नहीं होगी
  • रैंडम प्राइम्स दो मोडुली की शक्ति से बेहतर मिश्रण करते हैं और सभी बिट्स की जानकारी को केवल एक सबसेट नहीं बनाते हैं

हालांकि उनके पास एक बड़ा नकारात्मक पहलू है, उन्हें एक पूर्णांक विभाजन की आवश्यकता होती है, जो आधुनिक सीपीयू पर भी कई (~ 15-40) चक्र लेता है। लगभग आधे संगणना से यह सुनिश्चित किया जा सकता है कि हैश बहुत अच्छी तरह से मिलाया गया है। दो गुणा और xorshift संचालन एक प्रधान मौड्यूलस से बेहतर मिश्रण करेंगे। फिर हम जो भी हैश टेबल साइज का उपयोग कर सकते हैं और हैश रिडक्शन सबसे तेज है, 2 टेबल साइज की पावर के लिए कुल 7 ऑपरेशन और मनमाने साइज के करीब 9 ऑपरेशन कर सकते हैं।

मैंने हाल ही में सबसे तेज़ हैश तालिका कार्यान्वयन में से कई को देखा और उनमें से अधिकांश प्राइम मोडुली का उपयोग नहीं करते हैं।


0

इस प्रश्न को अधिक उपयुक्त प्रश्न के साथ मिला दिया गया था, हैश टेबल को प्राइम आकार के सरणियों का उपयोग क्यों करना चाहिए, न कि 2. की शक्ति के लिए। हैश कार्यों के लिए ही यहाँ बहुत सारे अच्छे उत्तर हैं, लेकिन संबंधित प्रश्न के लिए, कुछ सुरक्षा-महत्वपूर्ण हैश टेबल क्यों , glibc की तरह, प्राइम-आकार के सरणियों का उपयोग करें, अभी तक कोई नहीं है।

आम तौर पर 2 तालिकाओं की शक्ति बहुत तेज होती है। वहाँ महंगा है h % n => h & bitmask, जहां बिटमास्क की गणना clzn के आकार के ("अग्रणी अग्रणी शून्य") के माध्यम से की जा सकती है । एक मोड्यूलो फ़ंक्शन को पूर्णांक विभाजन करने की आवश्यकता होती है जो एक तार्किक की तुलना में लगभग 50x धीमी होती है and। एक मोडुलो से बचने के लिए कुछ ट्रिक्स हैं, जैसे लेमायर की https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ का उपयोग करना , लेकिन आम तौर पर तेजी से काम करने वाले टेबल पावर का उपयोग करते हैं। 2 के, और सुरक्षित हैश टेबल का उपयोग primes।

ऐसा क्यों?

इस मामले में सुरक्षा को टक्कर रिज़ॉल्यूशन रणनीति पर हमलों से परिभाषित किया गया है, जो टकराव की एक लिंक की गई सूची में सिर्फ रैखिक खोज के साथ अधिकांश हैश टेबल के साथ है। या सीधे तालिका में तेजी से खुले-संबोधित तालिकाओं के साथ रैखिक खोज। तो 2 टेबल की शक्ति और तालिका के कुछ आंतरिक ज्ञान, जैसे कि कुछ JSON इंटरफ़ेस द्वारा प्रदान की गई कुंजियों की सूची का आकार या क्रम, आपको सही बिट्स की संख्या का उपयोग किया जाता है। बिटमास्क पर लोगों की संख्या। यह आमतौर पर 10 बिट्स से कम होता है। और 5-10 बिट्स के लिए यह सबसे मजबूत और सबसे धीमी हैश फ़ंक्शन के साथ भी बल टकराव को तुच्छ है। अब आपको अपने 32 बिट या 64 बिट हैश फ़ंक्शन की पूर्ण सुरक्षा नहीं मिलती है। और यह बिंदु तेजी से छोटे हैश कार्यों का उपयोग करना है, न कि राक्षसों जैसे कि मुरमुर या सिपाश।

इसलिए यदि आप अपनी हैश टेबल पर एक बाहरी इंटरफ़ेस प्रदान करते हैं, जैसे कि एक डीएनएस रिसोल्वर, एक प्रोग्रामिंग भाषा, ... आप दुर्व्यवहार करने वाले लोगों की परवाह करना चाहते हैं जो ऐसी सेवाओं को डॉस करना पसंद करते हैं। ऐसे लोगों के लिए आम तौर पर आसान तरीकों के साथ अपनी सार्वजनिक सेवा को बंद करना आसान होता है, लेकिन ऐसा हुआ। इसलिए लोगों ने परवाह की।

तो ऐसे टकराव के हमलों से बचाव का सबसे अच्छा विकल्प या तो है

1) प्राइम टेबल का उपयोग करने के लिए, क्योंकि तब

  • सभी 32 या 64 बिट्स बाल्टी खोजने के लिए प्रासंगिक हैं, न कि केवल कुछ।
  • हैश तालिका आकार बदलने का कार्य केवल दोगुने से अधिक स्वाभाविक है। सबसे अच्छा विकास कार्य है, रिट्रेसमेंट अनुक्रम और primes दोहरीकरण की तुलना में करीब आते हैं।

2) वास्तविक हमले के खिलाफ बेहतर उपायों का उपयोग करें, साथ में 2 आकारों की तेज शक्ति।

  • टकराव और गर्भपात की गणना करें या पहचाने गए हमलों पर सोएं, जो कि टकराव की संख्या <1% की संभावना के साथ है। जैसे 32bit हैश टेबल के साथ 100। यह वही है जो djb की डीएनएस रिज़ॉल्वर करता है।
  • जब टकराव का पता चलता है तो O (लॉग एन) खोज को O (n) के साथ टकराने की लिंक की गई सूची में परिवर्तित करें। यह वह है जो जावा करता है।

एक विस्तृत प्रसार मिथक है कि अधिक सुरक्षित हैश फ़ंक्शंस ऐसे हमलों को रोकने में मदद करते हैं, जो कि गलत है जैसा कि मैंने समझाया। केवल कम बिट्स के साथ कोई सुरक्षा नहीं है। यह केवल प्राइम-आकार की तालिकाओं के साथ काम करेगा, लेकिन यह दो सबसे धीमे तरीकों के संयोजन का उपयोग करेगा, धीमी गति से हैश प्लस धीमा प्राइम्यूलो।

हैश टेबल के लिए हैश फ़ंक्शन मुख्य रूप से छोटे (इनलाइन करने योग्य) और तेज़ होने की आवश्यकता होती है। टक्करों में रैखिक खोज को रोकने से ही सुरक्षा आ सकती है। और तुच्छ बुरे हैश कार्यों का उपयोग नहीं करने के लिए, जैसे कुछ मूल्यों के प्रति असंवेदनशील (जैसे गुणा का उपयोग करते समय \ 0)।

यादृच्छिक बीजों का उपयोग करना भी एक अच्छा विकल्प है, लोगों ने पहले उस के साथ शुरुआत की, लेकिन तालिका की पर्याप्त जानकारी के साथ भी एक यादृच्छिक बीज बहुत मदद नहीं करता है, और गतिशील भाषाएं आमतौर पर बीज को अन्य तरीकों से प्राप्त करने के लिए तुच्छ बनाती हैं, क्योंकि यह संग्रहीत है। ज्ञात स्मृति स्थान।


-1
function eratosthenes(n) {

    function getPrime(x) {
        var middle = (x-(x%2))/2;
        var arr_rest = [];
        for(var j=2 ; j<=middle;j++){
            arr_rest.push(x%j);
        }

        if(arr_rest.indexOf(0) == -1) {
            return true
        }else {
            return false
        }

    }
    if(n<2)  {
        return []
    }else if(n==2){
        return [2]
    }else {
        var arr = [2]
        for(var i=3;i<n;i++) {
            if(getPrime(i)){
                arr.push(i)
            }
        }
    }

    return arr;
}

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