2010-04-07 6 views
5

मैं एक गणना है कि उत्पन्न करता है क्या फ्लोट 22.23, और एक शाब्दिक 22.23 इसलिए की तरह प्रतीत होता है है:रूबी 2 फ्लोट्स पर समानता क्यों विफल कर देगा?

some_object.total => 22.23 
some_object.total.class => Float 

22.23 => 22.23 
22.23.class => Float 

लेकिन किसी कारण से, निम्नलिखित गलत है:

some_object.total == 22.23 ? true : false 

निराला है, है ना ?

क्या किसी प्रकार की सटीक तंत्र का उपयोग किया जा रहा है जो शायद कुछ_object.total कॉल के माध्यम से पूरी तरह से पारदर्शी नहीं है?

+0

क्या रूबी के संस्करण? 1.8.6 में कुछ फ्लोट अंकगणितीय बग हैं। – mckeed

+0

हाय, आप फ्लोटिंग पॉइंट मुद्दों पर अपनी पोस्ट भी देख सकते हैं http://vladzloteanu.wordpress.com/2010/01/11/why-you-shouldnt-use-float-for-currency-floating-point-issues-explained -for-ruby-and-ror/ –

उत्तर

9

फ़्लोटिंग-पॉइंट संख्याएं निश्चित रूप से उनकी सीमा के भीतर सभी दशमलव संख्याओं का प्रतिनिधित्व नहीं कर सकती हैं। उदाहरण के लिए, 0.9 बिल्कुल 0.9 नहीं है, यह वास्तव में 0.9 के करीब एक संख्या है जो अधिकांश मामलों में हवाओं को मुद्रित किया जा रहा है। जैसे-जैसे आप फ़्लोटिंग-पॉइंट की गणना करते हैं, ये त्रुटियां जमा हो सकती हैं और आप सही संख्या के बहुत करीब के साथ हवादार हो जाते हैं लेकिन इसके बराबर नहीं होते हैं। उदाहरण के लिए, 0.3 * 3 == 0.9false लौटाएगा। यह हर कंप्यूटर भाषा में यह मामला है जिसका आप कभी भी उपयोग करेंगे - यह सिर्फ बाइनरी फ़्लोटिंग-पॉइंट गणित कैसे काम करता है। उदाहरण के लिए, this question about Haskell देखें।

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

def float_equal(a, b) 
    if a + 0.00001 > b and a - 0.00001 < b 
    true 
    else 
    false 
    end 
end 

आप रूबी में बिगडिसीमल कक्षा का भी मनमाने ढंग से दशमलव संख्याओं का प्रतिनिधित्व करने के लिए उपयोग कर सकते हैं।

यह एक परीक्षण मामला है, तो आप assert_in_delta उपयोग कर सकते हैं:

def test_some_object_total_is_calculated_correctly 
    assert_in_delta 22.23, some_object.total, 0.01 
end 
+0

यूप, इससे मदद मिलती है! धन्यवाद! – btelles

+2

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

+0

धन्यवाद भाई। Assert_in_delta विधि मेरे लिए यह किया था। मुझे मिल रहा था: "<3375.0> अपेक्षित था लेकिन <3375.0> था" और यह नहीं समझा कि क्या हो रहा था! – mjnissim

1

यहां कुछ और चल रहा है। यह एक 1.8.7 आईआरबी

irb(main):001:0> class Test 
irb(main):002:1> attr_accessor :thing 
irb(main):003:1> end 
=> nil 
irb(main):004:0> t = Test.new 
=> #<Test:0x480ab78> 
irb(main):005:0> t.thing = 22.5 
=> 22.5 
irb(main):006:0> t.thing == 22.5 
=> true 
+0

कुल वास्तव में योग और कई अन्य संख्याओं की गणना है, जिससे त्रुटियां उत्पन्न होती हैं। – btelles

6

Float#to_s और Float#inspect दौर से है। "%.30f" % some_object.total आज़माएं और आप देखेंगे कि यह काफी 22.23 नहीं है।

+0

हे ... "22.229 99 99 99 99 9996873611962655559" यही वह है। धन्यवाद। – btelles

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