अनुमानित समानता के साथ फ्लोट हैशिंग को कैसे लागू किया जाए


15

मान लें कि हमारे पास निम्नलिखित पायथन वर्ग है (जावा में समस्या केवल उसी के साथ मौजूद है equalsऔर hashCode)

class Temperature:
    def __init__(self, degrees):
        self.degrees = degrees

degreesकेल्विन में एक फ्लोट के रूप में तापमान कहां है। अब, मैं समानता परीक्षण लागू करना चाहता हूं और Temperatureएक तरह से इसके लिए हैशिंग

  • प्रत्यक्ष समानता परीक्षण के बजाय एक एप्सिलॉन अंतर पर तैरने की तुलना करता है,
  • और उस अनुबंध का सम्मान करता है जिसका a == bतात्पर्य है hash(a) == hash(b)
def __eq__(self, other):
    return abs(self.degrees - other.degrees) < EPSILON

def __hash__(self):
    return # What goes here?

पायथन प्रलेखन यह सुनिश्चित करने के लिए हैशिंग संख्या के बारे में थोड़ी बात करता है hash(2) == hash(2.0)लेकिन यह काफी समान समस्या नहीं है।

क्या मैं भी सही रास्ते पर हूँ? और यदि हां, तो इस स्थिति में हैशिंग को लागू करने का मानक तरीका क्या है?

अपडेट : अब मैं समझता हूँ कि समानता तैरता के लिए परीक्षण के इस प्रकार के संक्रामिता समाप्त ==और equals। लेकिन यह कैसे "सामान्य ज्ञान" के साथ मिलकर चलता है कि तैरने की तुलना सीधे नहीं की जानी चाहिए? यदि आप फ़्लोट्स की तुलना करके एक समानता ऑपरेटर को लागू करते हैं, तो स्थैतिक विश्लेषण उपकरण शिकायत करेंगे। क्या वे ऐसा करने के लिए सही हैं?


9
प्रश्न में जावा का टैग क्यों है?
लाविस

8
आपके अपडेट के बारे में: मैं कहूंगा कि हैशिंग फ्लोट आम तौर पर एक संदिग्ध बात है। कुंजियों के रूप में या सेट तत्वों के रूप में फ़्लोट्स के उपयोग से बचने की कोशिश करें।
जे। फबियन मियर

6
@ नील: एक ही समय में, पूर्णांक की तरह ध्वनि को गोल नहीं करता है? इससे मेरा मतलब है: यदि आप डिग्री के हजारवें हिस्से तक कह सकते हैं, तो आप बस एक निश्चित-बिंदु प्रतिनिधित्व का उपयोग कर सकते हैं - डिग्री के हजारवें हिस्से में तापमान को व्यक्त करने वाला पूर्णांक। उपयोग में आसानी के लिए, आप एक गेटर / सेटर को पारदर्शी रूप से / फ्लोट से परिवर्तित कर सकते हैं यदि आप चाहें ...
Matthieu M.

4
केल्विन अब डिग्री नहीं हैं। डिग्री भी अस्पष्ट हैं। सिर्फ इसे क्यों नहीं कहते kelvin?
सोलोमन उको

5
पायथन में अधिक या कम उत्कृष्ट निश्चित-बिंदु समर्थन है , हो सकता है कि यह आपके लिए कुछ हो।
जोनास स्चफर

जवाबों:


41

समानता परीक्षण लागू करें और तापमान के लिए हैशिंग की तुलना इस तरह से करें कि सीधी समानता परीक्षण के बजाय एक एप्सिलॉन अंतर तक तैरता है,

फजी समानता आवश्यकताओं का उल्लंघन करती है कि जावा पर स्थानों equalsविधि, अर्थात् संक्रामिता , यानी कि अगर x == yऔर y == z, फिर x == z। लेकिन अगर आप उदाहरण के लिए, 0.1 के एप्सिलॉन के साथ एक फजी समानता करते हैं, तो 0.1 == 0.2और 0.2 == 0.3, लेकिन 0.1 == 0.3पकड़ नहीं है।

जबकि पायथन इस तरह की आवश्यकता का दस्तावेज नहीं करता है, फिर भी एक गैर-सकर्मक समानता होने के निहितार्थ इसे एक बहुत बुरा विचार बनाते हैं; इस प्रकार के कारणों के बारे में सिरदर्द-उत्प्रेरण है।

तो मैं दृढ़ता से अनुशंसा करता हूं कि आप ऐसा न करें।

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

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


2
दिलचस्प विचार। तो लाखों एप्सिलॉन को संचित करके और परिवर्तनशीलता के साथ आप यह निष्कर्ष निकाल सकते हैं कि कुछ भी किसी भी चीज़ के बराबर है :-) लेकिन क्या यह गणितीय बाधा फ़्लोटिंग पॉइंट्स की असतत नींव को स्वीकार करती है, जो कि कई मामलों में संख्या का अनुमान लगाने का इरादा है?
क्रिस्टोफ

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

@ ओपी के संपादन को संबोधित करते हुए, मैं यह जोड़ूंगा कि फ्लोटिंग-पॉइंट की गलतता में उनके प्रकार के =="संक्रमित" होने चाहिए ==। यही है, अगर वे एक सटीक समानता प्रदान करने की आपकी सलाह का पालन करते हैं, तो उनके स्थैतिक विश्लेषण उपकरण को आगे चेतावनी दी जानी चाहिए कि समानता का उपयोग कब किया जाए Temperature। यह केवल एक चीज है जो आप कर सकते हैं, वास्तव में।
HTNW

@ एचटीएनडब्ल्यू: यह बहुत सरल होगा। एक अनुपात वर्ग में एक float approximationक्षेत्र हो सकता है जो भाग नहीं लेता है ==। इसके अलावा, स्थैतिक विश्लेषण उपकरण पहले से ही ==कक्षाओं के कार्यान्वयन के अंदर एक चेतावनी देगा जब सदस्यों में से एक की तुलना एक floatप्रकार है।
MSalters

@ मालिक? मुमकिन है, पर्याप्त रूप से कॉन्फ़िगर किए गए स्थिर विश्लेषण उपकरण वही कर सकते हैं जो मैंने ठीक-ठीक सुझाया था। यदि किसी वर्ग के पास एक ऐसा floatक्षेत्र है जो भाग नहीं लेता है ==, तो ==उस वर्ग को चेतावनी देने के लिए अपने टूल को कॉन्फ़िगर न करें । यदि वर्ग करता है, तो संभवतः कक्षा ==को "बहुत सटीक" के रूप में चिह्नित करना उपकरण को कार्यान्वयन के भीतर उस तरह की त्रुटि को अनदेखा करने का कारण होगा। जैसे जावा में, यदि @Deprecated void foo(), तो void bar() { foo(); }एक चेतावनी है, लेकिन @Deprecated void bar() { foo(); }नहीं है। शायद कई उपकरण इस का समर्थन नहीं करते हैं, लेकिन कुछ कर सकते हैं।
HTNW

16

शुभ लाभ

आप इसे प्राप्त करने में सक्षम नहीं होंगे, बिना हैश के साथ बेवकूफ़ बने रहेंगे, या एप्सिलॉन का त्याग करेंगे।

उदाहरण:

मान लें कि प्रत्येक बिंदु अपने स्वयं के अनूठे हैश मूल्य के लिए हैश करता है।

चूंकि फ़्लोटिंग पॉइंट नंबर अनुक्रमिक होते हैं, किसी दिए गए फ़्लोटिंग पॉइंट मान से पहले k नंबर तक होंगे, और दिए गए फ़्लोटिंग पॉइंट मान के बाद k नंबर तक होंगे जो दिए गए बिंदु के कुछ एप्सिलॉन के भीतर हैं।

  1. एक दूसरे के epsilon के भीतर प्रत्येक दो बिंदुओं के लिए जो समान हैश मान साझा नहीं करते हैं।

    • हैशिंग स्कीम को समायोजित करें ताकि इन दोनों बिंदुओं को एक ही मूल्य पर हैश किया जा सके।
  2. ऐसी सभी जोड़ियों के लिए प्रेरित करने पर फ्लोटिंग पॉइंट नंबरों का पूरा क्रम एक एकल मूल्य की ओर ढह जाएगा।

कुछ मामले हैं जहां यह सच नहीं होगा:

  • सकारात्मक / नकारात्मक इन्फिनिटी
  • NaN
  • कुछ डी-सामान्यीकृत श्रेणियां जो किसी दिए गए एप्सिलॉन के लिए मुख्य रेंज से लिंक करने योग्य नहीं हो सकती हैं।
  • शायद कुछ अन्य प्रारूप विशिष्ट उदाहरण हैं

हालाँकि> = = 99% फ़्लोटिंग पॉइंट रेंज किसी भी मान के लिए हैशिलोन के लिए हैश होगा जिसमें कुछ दिए गए फ़्लोटिंग पॉइंट वैल्यू के ऊपर या नीचे कम से कम एक फ़्लोटिंग पॉइंट वैल्यू शामिल है।

परिणाम

या तो> = 99% संपूर्ण फ़्लोटिंग पॉइंट रेंज हैश एक मूल्य के इरादे को गंभीरता से सम्‍मिलित करता है (और किसी भी उपकरण / कंटेनर को काफी वितरित कम-टकराव हैश पर निर्भर करता है)।

या एप्सिलॉन ऐसा है जिसमें केवल सटीक मिलान की अनुमति है।

दानेदार

आप निश्चित रूप से इसके बजाय एक दानेदार दृष्टिकोण के लिए जा सकते हैं।

इस दृष्टिकोण के तहत आप एक विशेष संकल्प के नीचे सटीक बाल्टियों को परिभाषित करते हैं। अर्थात:

[0.001, 0.002)
[0.002, 0.003)
[0.003, 0.004)
...
[122.999, 123.000)
...

प्रत्येक बाल्टी में एक अद्वितीय हैश होता है, और बाल्टी के भीतर कोई भी फ्लोटिंग पॉइंट एक ही बाल्टी में किसी अन्य फ्लोट के बराबर होता है।

दुर्भाग्य से यह अभी भी संभव है कि दो फ़्लोट्स के लिए एप्सिलॉन दूरी दूर हो, और दो अलग-अलग हैश हो।


2
मैं सहमत हूं कि अगर यहां ओपी की आवश्यकताओं को पूरा किया जाता है, तो यहां का ग्रैन्युलर एप्रोच शायद सबसे अच्छा होगा। हालांकि मुझे डर है कि ओपी के पास +/- 0.1% प्रकार की आवश्यकताएं हैं, जिसका अर्थ है कि यह दानेदार नहीं हो सकता है।
नील

4
@DocBrown "संभव नहीं" भाग सही है। यदि एप्सिलॉन आधारित समानता का अर्थ यह होना चाहिए कि हैश कोड समान हैं, तो आपके पास स्वचालित रूप से सभी हैश कोड समान हैं, इसलिए हैश फ़ंक्शन अब उपयोगी नहीं है। बाल्टियाँ दृष्टिकोण फलदायी हो सकती हैं, लेकिन आपके पास अलग-अलग हैश कोड के साथ संख्याएँ होंगी जो मनमाने ढंग से एक दूसरे के करीब होती हैं।
जे फैबियन मीयर

2
बाल्टी के दृष्टिकोण को सटीक हैश कुंजी के साथ न केवल बाल्टी की जांच करके संशोधित किया जा सकता है, बल्कि दो पड़ोसी बाल्टियों (या उनमें से कम से कम एक) के रूप में भी उनकी सामग्री के लिए। कि ज्यादातर दो (जब यह सही ढंग से लागू किया जाता है) के एक कारक द्वारा चल रहे समय को बढ़ाने की लागत के लिए उन किनारे के मामलों की समस्या को समाप्त करता है। हालांकि, यह सामान्य रनिंग टाइम ऑर्डर को नहीं बदलता है।
डॉक ब्राउन

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

1
@CarstenS हाँ, मेरा कथन है कि 99% रेंज हैश करने के लिए एक हैश वास्तव में पूरे फ्लोट रेंज को कवर नहीं करता है। कई उच्च श्रेणी के मान हैं जो एप्सिलॉन से अधिक से अलग होते हैं जो अपने स्वयं के अनूठे बकेट को हैश करेंगे।
Kain0_0

7

आप अपने तापमान को हुड के नीचे एक पूर्णांक के रूप में मॉडल कर सकते हैं। तापमान में प्राकृतिक रूप से कम बाउंड (-273.15 सेल्सियस) होता है। तो, डबल (-273.15 आपके अंतर्निहित पूर्णांक के लिए 0 के बराबर है)। दूसरा तत्व जो आपको चाहिए वह है आपकी मैपिंग की ग्रैन्युलैरिटी। आप पहले से ही इस ग्रैन्युलैरिटी का उपयोग कर रहे हैं; यह आपका EPSILON है।

बस अपना तापमान EPSILON से विभाजित करें और इसका फर्श लें, अब आपका हैश और आपके समतुल्य व्यवहार होगा। पायथन 3 में पूर्णांक अनबाउंड है, अगर आप चाहें तो EPSILON छोटा हो सकता है।

सावधान आप एप्सिलॉन का मूल्य बदल है और आप वस्तु धारावाहिक है कि वे संगत नहीं होगा!

#Pseudo code
class Temperature:
    def __init__(self, degrees):
        #CHECK INVALID VALUES HERE
        #TRANSFORM TO KELVIN HERE
        self.degrees = Math.floor(kelvin/EPSILON)

1

फ़्लोटिंग-पॉइंट हैश टेबल को लागू करना, जो उन चीज़ों को ढूंढ सकता है जो किसी दिए गए कुंजी के "लगभग बराबर" हैं, इसके लिए कुछ दृष्टिकोणों या एक संयोजन का उपयोग करने की आवश्यकता होगी:

  1. प्रत्येक मान को एक वृद्धि के लिए गोल करें, जो हैश तालिका में संग्रहीत करने से पहले "फ़ज़ी" रेंज से कुछ बड़ा होता है, और जब कोई मान ढूंढने का प्रयास किया जाता है, तो मांगे गए मान के ऊपर और नीचे गोल मूल्यों के लिए हैश तालिका की जाँच करें।

  2. प्रत्येक आइटम को हैश तालिका के भीतर उन कुंजियों का उपयोग करके स्टोर करें जो मांगी जा रही मूल्य से ऊपर और नीचे हैं।

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


0

आप निश्चित रूप से मंटिसा के अंतिम आठ बिट्स को हटाकर और फिर तुलना या हैशिंग द्वारा "लगभग बराबर" को परिभाषित कर सकते हैं। समस्या यह है कि एक दूसरे के बहुत निकट संख्या भिन्न हो सकती है।

यहाँ कुछ भ्रम है: यदि दो फ़्लोटिंग पॉइंट संख्या की तुलना समान है, तो वे समान हैं। यह जाँचने के लिए कि क्या वे समान हैं, आप "==" का उपयोग करें। कभी-कभी आप समानता की जांच नहीं करना चाहते हैं, लेकिन जब आप करते हैं, तो "==" जाने का रास्ता है।


0

यह कोई जवाब नहीं है, लेकिन एक विस्तारित टिप्पणी जो सहायक हो सकती है।

मैं MPFR (GNU MP पर आधारित) का उपयोग करते हुए एक समान समस्या पर काम कर रहा हूं । @ Kain0_0 द्वारा उल्लिखित "बकेट" दृष्टिकोण स्वीकार्य परिणाम देता है, लेकिन उस उत्तर में उल्लिखित सीमाओं से अवगत रहें।

मैं इसे जोड़ना चाहता था - आप जो करने की कोशिश कर रहे हैं उसके आधार पर - गणितज्ञ जैसे "सटीक" ( कैविट एम्प्टर ) कंप्यूटर बीजगणित प्रणाली का उपयोग करके अनुपूरक संख्यात्मक कार्यक्रम को पूरक या सत्यापित करने में मदद मिल सकती है। यह आपको गोलाई के बारे में चिंता किए बिना परिणामों की गणना करने की अनुमति देगा, उदाहरण के लिए, या इसके बजाय 7*√2 - 5*√2उपज देगा । बेशक, यह अतिरिक्त जटिलताओं का परिचय देगा जो इसके लायक हो सकते हैं या नहीं।22.00000001

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