2010-12-08 10 views
9

के साथ एक वर्ग के लिए "सहिष्णु" `बराबर 'और' हैशकोड 'लागू करें मेरे पास float फ़ील्ड वाला एक वर्ग है। उदाहरण के लिए:फ्लोटिंग पॉइंट सदस्यों

public class MultipleFields { 
    final int count; 
    final float floatValue; 

    public MultipleFields(int count, float floatValue) { 
    this.count = count; 
    this.floatValue = floatValue; 
    } 

} 

मुझे मूल्य से उदाहरणों की तुलना करने में सक्षम होना चाहिए। अब मैं equals & hashCode को सही तरीके से कैसे कार्यान्वित कर सकता हूं?

equals और hashCode को लागू करने का सामान्य तरीका सभी क्षेत्रों पर विचार करना है। जैसे ग्रहण निम्नलिखित equals उत्पन्न करेगा:

public boolean equals(Object obj) { 
    // irrelevant type checks removed 
    .... 
    MultipleFields other = (MultipleFields) obj; 
    if (count != other.count) 
     return false; 
    if (Float.floatToIntBits(floatValue) != Float.floatToIntBits(other.floatValue)) 
     return false; 
    return true; 
    } 

(और एक समान hashCode, कि अनिवार्य रूप से count* 31 + Float.floatToIntBits(floatValue) गणना करता है)।

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

सामान्य समाधान एक ईपीएसलॉन मान का उपयोग करके तुलना करना है (उदा। Comparing IEEE floats and doubles for equality देखें)। हालांकि, मुझे यकीन नहीं है कि मैं इस विधि का उपयोग करके equals को कैसे कार्यान्वित कर सकता हूं, और अभी भी है जो equals के साथ है।

long comparisonFloatValue = Math.round(floatValue* (Math.pow(10, RELEVANT_DIGITS))); 
फिर

अगर मैं equals में comparisonFloatValue साथ floatValue के सभी उपयोगों की जगह:

मेरा विचार सार्थक अंकों की संख्या की तुलना के लिए, तो हमेशा दौर अंकों की उस नंबर पर दोनों equals और hashCode में परिभाषित करने के लिए है और hashCode, मुझे "सहनशील" तुलना मिलनी चाहिए, जो hashCode के अनुरूप है।

  • क्या यह काम करेगा?
  • क्या आपको इस दृष्टिकोण के साथ कोई समस्या है?
  • क्या ऐसा करने का कोई बेहतर तरीका है? यह बल्कि जटिल लगता है।
+0

क्या आपने अभी फ़्लोटिंग-पॉइंट ** का उपयोग नहीं किया है और इसके बजाय एक निश्चित-बिंदु प्रतिनिधित्व पर स्विच किया है? –

+0

@ करल: हाँ, अच्छा बिंदु, और हाँ, मैंने किया। समस्या यह है कि डीबी में मूल्य एफपी (जो बदलना मुश्किल है, क्योंकि यह हमारे नियंत्रण में नहीं है), इसलिए मुझे डीबी से पढ़ने के दौरान गोल करना होगा। मैं ऐसा नहीं करना चाहता, क्योंकि मुझे लगता है कि आंतरिक रूप से एफपी का उपयोग करना और आउटपुट पर केवल गोल करना बेहतर है। – sleske

+0

ओह, बस ध्यान दिया कि मैंने^ऑपरेटर का उपयोग किया था। बेशक मेरा मतलब एक्सपोनेंटिएशन था, बाइनरी ऑपरेटर नहीं। 'Math.pow' का उपयोग करने के लिए फिक्स्ड। – sleske

उत्तर

10

इसके साथ बड़ी समस्या है कि दो नाव मूल्यों अभी भी बहुत करीब एक साथ हो सकता है, लेकिन अभी भी असमान तुलना है। असल में आप फ्लोटिंग पॉइंट मानों की सीमा को बाल्टी में विभाजित कर रहे हैं - और एक ही बाल्टी में बिना दो मान एक साथ बहुत करीब हो सकते हैं। कल्पना कीजिए कि आप दो महत्वपूर्ण अंक का उपयोग कर रहे थे, बाल्टी प्राप्त करने के लिए छंटनी लागू कर रहे थे, उदाहरण के लिए ... फिर 11.9 99 999 और 12.000001 असमान होंगे, लेकिन एक दूसरे से अलग होने के बावजूद 12.000001 और 12.9 99 99 99 बराबर होंगे।

दुर्भाग्य से, यदि आप इस तरह के बाल्टी मान नहीं हैं, तो आप पारगमन की वजह से उचित रूप से बराबर लागू नहीं कर सकते हैं: x और y एक साथ बंद हो सकते हैं, y और z एक साथ हो सकते हैं, लेकिन यह नहीं है मतलब है कि एक्स और जेड एक साथ बंद हैं।

+0

क्षमा करें, मेरी तुलना FloatValue की गणना गलत तरीके से की गई थी (मुझे विश्वास था कि जावा एक्सपोनिएशन के लिए '^' का उपयोग करता है :-()। मेरे उत्तर को संपादित किया गया। इस तरह, 0.9 99 99 99 99 99 999 और 1.0000000001 को समान के रूप में तुलना करना चाहिए, जब तक कि आप 9 से अधिक या उससे अधिक समय तक RELEVANT_DIGITS सेट न करें। – sleske

+0

बेशक, आपका बिंदु अभी भी खड़ा है: यदि वे अलग-अलग बाल्टी में आते हैं तो दो एफपी मूल्यों को मेरे कार्यान्वयन में अलग माना जाएगा, और यह एफपी संख्याओं के लिए हो सकता है जो मनमाने ढंग से एक साथ बंद हो जाते हैं। इसलिए यह "सहिष्णु तुलना" नहीं देता है: - ( – sleske

+0

@sleske: जावा एक्सपोनेंटिएशन के लिए^का उपयोग नहीं करता है - यह एक्सओआर है। एक्सपोनेंटिएशन के लिए Math.pow का उपयोग करें। मेरा उदाहरण शायद दुर्भाग्यपूर्ण था - मैं संपादित करूंगा। लेकिन हाँ, आपको मूल रूप से अपनी आवश्यकताओं को पूरा करने की आवश्यकता है :) –

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^