2010-08-05 10 views
6

तो मैं इस मुद्दे में जा रहा हूं ... मेरे पास बहुत अधिक इस्तेमाल किया जाने वाला वेब एप्लिकेशन है, जो कि 2 वर्षों में पहली बार समानता समारोह का उपयोग करते हुए दो युगल पर समानता जांच करने में असफल रहा, एक सहयोगी ने कहा वह वर्षों से भी इस्तेमाल कर रहा था।.NET में दो युगल की समानता की जांच के साथ समस्याएं - इस विधि के साथ क्या गलत है?

जिस फ़ंक्शन में मैं पेस्ट करने जा रहा हूं उसका लक्ष्य दो डबल मानों की तुलना सटीकता के 4 अंकों से करना और तुलना परिणामों को वापस करना है। उदाहरण के लिए, मेरी मान हैं:

Dim double1 As Double = 0.14625000000000002 ' The result of a calculation 
Dim double2 As Double = 0.14625 ' A value that was looked up in a DB 

तो मैं उन्हें इस समारोह में पारित:

Public Shared Function AreEqual(ByVal double1 As Double, ByVal double2 As Double) As Boolean 

    Return (CType(double1 * 10000, Long) = CType(double2 * 10000, Long)) 

End Function 

तुलना विफल रहता है। गुणन और लांग के लिए कलाकारों के बाद, तुलना से किया जा रहा समाप्त होता है:

Return 1463 = 1462 

मैं यहाँ अपने खुद के सवाल का जवाब देने की तरह हूँ, लेकिन मैं देख सकता हूँ कि double1 एक डबल (17 अंक) की शुद्धता के भीतर है और कास्ट सही ढंग से काम कर रहा है।

मेरा पहला वास्तविक सवाल यह है: यदि मैं ऊपर दी गई रेखा को निम्न में बदलता हूं, तो यह सही तरीके से क्यों काम करता है (True देता है)?

Return (CType(CType(double1, Decimal) * 10000, Long) = _ 
    CType(CType(double2, Decimal) * 10000, Long)) 

करता नहीं Decimal है और भी अधिक सटीक है, इस प्रकार लंबी करने के लिए कलाकारों अभी भी 1463, और तुलना लौट False होना चाहिए? मुझे लगता है कि मुझे इस सामान पर मस्तिष्क का फट है ...

दूसरा, अगर कोई तुलना करने के लिए इस फ़ंक्शन को बदलना था तो मैं अधिक सटीक या कम त्रुटि प्रवण की तलाश में हूं, क्या आप इसे बदलने की अनुशंसा करेंगे कुछ आसान है? उदाहरण के लिए:

Return (Math.Abs(double1 - double2) < 0.0001) 

मैं की तरह कुछ कोशिश करने के लिए पागल हो:

Return (double1.ToString("N5").Equals(double2.ToString("N5"))) 

(मैं ऊपर ऐसा कभी नहीं होगा, मैं आपकी प्रतिक्रियाओं के बारे में बस उत्सुक हूँ यह में बुरी तरह अक्षम होगा मेरी। आवेदन।)

वैसे भी, अगर कोई अंतर पर कुछ प्रकाश डाल सकता है तो मैं Double एस और Decimal से Long कास्टिंग के बीच देख रहा हूं, यह बहुत अच्छा होगा।

धन्यवाद!

उत्तर

3

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

मैं दृढ़ता से आपको बिना किसी कलाकार के तुलनात्मक कोड लिखने की सलाह दूंगा। आपका Math.Abs ​​लाइन पूरी तरह से ठीक है।

मेरा पहला असली सवाल यह है:: यदि मैं निम्नलिखित करने के लिए लाइन बदलने के ऊपर, क्यों इसे सही ढंग से काम करता है (यह सच रिटर्न)

अपने पहले प्रश्न के बारे में

?

कारण यह है कि डबल से दशमलव तक कास्ट परिशुद्धता खो रहा है, जिसके परिणामस्वरूप 0.1425 से 0.1425 की तुलना होती है।

+0

"... डबल से दशमलव तक कास्ट सटीक खो रहा है ..." इससे मेरा दिमाग दुख पहुंचाता है। परिशुद्धता क्यों गुम हो जाती है? ऐसा इसलिए है क्योंकि एक दशमलव एक डबल से अलग आधार है; यानी यह इसलिए है क्योंकि संख्याएं अलग-अलग संग्रहित होती हैं? –

+0

कोई बात नहीं। मैं बिना सोच के टाइप कर रहा हूँ। मेरा मतलब था कि कास्ट संकुचित हो रहा था (यानी जानकारी खोना), जो यह है, लेकिन मुझे नुकसान क्यों हुआ है। दशमलव दस्तावेज के अनुसार, डबल से दशमलव तक कास्टिंग कुछ भी नहीं खोता है, लेकिन डीबगर छोटे हिस्से को गायब कर रहा है: यानी डिम टेस्ट के रूप में नया दशमलव (0.14625000000000002) परिणामस्वरूप 0.14625 युक्त परीक्षण होता है। हालांकि, डिम टेस्ट के रूप में दशमलव = 0.14625000000000002D काम करता है। मैं फ़्लोटिंग पॉइंट अंकगणितीय के बारे में लिंक्ड आलेख पढ़ूंगा और इस बिंदु पर जवाब देना बंद कर दूंगा ... –

+2

और कुछ और दस्तावेज के माध्यम से खोज से पता चलता है: "यह कन्स्ट्रक्टर राउंड निकटतम के लिए गोल करके 15 महत्वपूर्ण अंकों के लिए मूल्यवान है। यह तब भी किया जाता है जब यह किया जाता है संख्या में 15 से अधिक अंक हैं और कम महत्वपूर्ण अंक शून्य हैं।" –

4
+0

मुझे यकीन नहीं है कि समस्या फ्लोटिंग पॉइंट अंकगणित की गलतफहमी है। समस्या फ्लोटिंग पॉइंट अंकगणितीय को ठीक करने और ठीक करने के लिए एक कास्ट का उपयोग कर रही है। –

+0

@ जेसन बर्कन - कलाकारों का उपयोग गलतफहमी को दर्शाता है। –

+0

जैसा मैंने कहा था, कोड एक सहयोगी है और वह मानता है कि यह पर्याप्त होगा - मुझे डिबगिंग करने का काम सौंपा गया था। ओपी में 'Math.Abs ​​()' समाधान मैंने फेंक दिया था, मेरा सुझाव एक फिक्स के रूप में था, मैं सिर्फ प्रकार के कास्टिंग मुद्दे के बारे में अधिक समझना चाहता था ताकि मैं भविष्य में इससे बच सकूं। मेरे पद में उदाहरण केवल कास्टिंग व्यवहार की जिज्ञासा का परिणाम थे, जिसके लिए मुझे स्पष्ट रूप से अधिक शोध करने की आवश्यकता है। –

2

आप CType का उपयोग करते हैं, तो आप अपने कार्यक्रम को बता रहे हैं "मुझे परवाह नहीं है कैसे आप संख्याओं दौर, बस यकीन है कि परिणाम बनाने के इस दूसरे प्रकार है।" संख्याओं की तुलना करते समय यह बिल्कुल सही नहीं है कि आप अपने कार्यक्रम में क्या कहना चाहते हैं।

चल बिन्दु संख्या की तुलना करना एक दर्द है और मैं कभी भी किसी भी भाषा में एक Round समारोह पर भरोसा नहीं होगा जब तक आप जानते हैं कि वास्तव में यह कैसे बर्ताव करता है (उदाहरण के लिए कभी कभी यह .5 अप और कभी कभी नीचे दौर, पिछले पर निर्भर करता है संख्या ... यह एक गड़बड़ है)।

.NET में, मैं वास्तव में अपने डबल मान को गुणा करने के बाद Math.Truncate() का उपयोग कर सकता हूं।तो, Math.Truncate(.14625 * 10000) (जो Math.Truncate(1462.5) है) 1462 के बराबर होगा क्योंकि यह सभी दशमलव मानों से छुटकारा पाता है। अपने उदाहरण से डेटा के साथ Truncate() का उपयोग करके, दोनों मान बराबर हो जाएंगे क्योंकि 1) वे युगल रहते हैं और 2) आपने सुनिश्चित किया है कि दशमलव प्रत्येक से हटा दिया गया था।

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

+0

मैं असहमत हूं, स्ट्रिंग तुलना अत्यधिक जटिल है। फ़ंक्शन के लिए विनिर्देश यह है कि यदि संख्याओं के बीच का अंतर '0.0001' से कम है, तो 'AreEqual' होना चाहिए' सही' होना चाहिए। दूसरे शब्दों में, 'AreEqual = (Math.Abs ​​(डबल 1 - डबल 2) <0.0001) ' – MarkJ

+0

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

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