2009-04-15 5 views
8

निम्न प्रोग्राम प्रिंट करता है जो प्रिंट करता है?सी # अपर्याप्त में अस्थायी बिंदु अंकगणित क्यों है?

class Program 
{ 
    static void Main(string[] args) 
    { 
     float f1 = 0.09f*100f; 
     float f2 = 0.09f*99.999999f; 

     Console.WriteLine(f1 > f2); 
    } 
} 

आउटपुट

false 
+0

आप इसे अपने लिए क्यों नहीं देखते हैं? –

+10

मैंने कोशिश की, मैं सिर्फ यह जानना चाहता हूं कि मैं जो देखता हूं उसे देखता हूं। – Prankster

+1

[भाषा-अज्ञेयवादी - क्या फ़्लोटिंग पॉइंट गणित टूटा हुआ है?] (Http://stackoverflow.com/q/588004/995714) –

उत्तर

30

चल बिन्दु केवल परिशुद्धता के इतने अंक है। यदि आप f1 == f2 देख रहे हैं, तो ऐसा इसलिए है क्योंकि 32-बिट फ्लोट की तुलना में किसी भी अंतर को अधिक सटीकता की आवश्यकता होती है।

मेरा सुझाव पढ़ने What Every Computer Scientist Should Read About Floating Point

+0

+1 क्यों, सबमिट बटन को मारने के बाद मैं क्यों देखूं कि किसी ने लिंक पोस्ट किए हैं? : पी – dirkgently

+1

+1 http://msdn.microsoft.com/en-us/library/b1e65aza(VS.71).aspx माइकल सही है, सी # फ्लोट में केवल 7 अंकों की सटीकता है, और 99.9 99 99 9एफ में 8 अंक हैं। – James

+6

यह सी # विशिष्ट नहीं है। एक सिंगल-प्रेसिजन आईईईई -754 फ्लोट केवल 32-बिट्स होगा, जो परिशुद्धता के लगभग 7 दशमलव अंक देता है। यदि आप इससे बेहतर चाहते हैं, तो डबल का उपयोग करें। – Wedge

5

मुख्य बात यह है कि यह सिर्फ नेट नहीं है: यह स्मृति में underlying system most every language will use to represent a float की एक सीमा है। परिशुद्धता केवल अब तक जाती है।

आप अपेक्षाकृत सरल संख्याओं के साथ कुछ मज़ेदार भी हो सकते हैं, जब आप ध्यान में रखते हैं कि यह आधार दस भी नहीं है। 0.1, उदाहरण के लिए, द्विआधारी में प्रतिनिधित्व करते समय एक दोहराव दशमलव है।

3

इस विशेष मामले में, ऐसा इसलिए है क्योंकि .0 9 और। 99 99 99 को बाइनरी में सटीक सटीकता के साथ प्रदर्शित नहीं किया जा सकता है (इसी प्रकार, 1/3 दशमलव में सटीक सटीकता के साथ प्रदर्शित नहीं किया जा सकता है)। उदाहरण के लिए, 0.111111111111111111101111 बेस 2 0.9 99 998986721038818359375 आधार 10 है। पिछले बाइनरी मान में 1 जोड़ना, 0.11111111111111111111 बेस 2 0.99999904632568359375 आधार 10 है। बिल्कुल 0.999 999 के लिए बाइनरी मान नहीं है। फ्लोटिंग पॉइंट परिशुद्धता भी घाटी के विस्तारक और आंशिक हिस्से को संग्रहित करने के लिए आवंटित स्थान से सीमित है। इसके अलावा, पूर्णांक प्रकारों की तरह, फ़्लोटिंग पॉइंट इसकी सीमा को ओवरफ़्लो कर सकता है, हालांकि इसकी सीमा पूर्णांक श्रेणियों से बड़ी है।

Xcode डिबगर में सी ++ कोड के इस बिट,

नाव myFloat = 0.1 चल रहा है;

दिखाता है कि MyFloat को 0.100000001 मान मिलता है। यह 0.000000001 से बंद है। बहुत कुछ नहीं, लेकिन यदि गणना में कई अंकगणितीय परिचालन हैं, तो अपर्याप्तता को जोड़ा जा सकता है।

imho चल बिन्दु का एक बहुत अच्छा विवरण (सेवानिवृत्त) http://bob.cs.sonoma.edu/getting_book.html सोनोमा में x86-64 विधानसभा भाषा & जीएनयू/लिनक्स कैलिफोर्निया स्टेट यूनिवर्सिटी के बॉब Plantz द्वारा साथ कंप्यूटर संगठन को परिचय के अध्याय 14 में है। निम्नलिखित उस अध्याय पर आधारित है।

फ़्लोटिंग पॉइंट वैज्ञानिक नोटेशन की तरह है, जहां एक मान 1.0 के बराबर या बराबर मिश्रित संख्या के रूप में संग्रहीत किया जाता है और 2.0 से कम (मंटिसा), कुछ शक्ति (एक्सपोनेंट) के लिए दूसरी संख्या होती है। फ़्लोटिंग पॉइंट बेस 10 के बजाए आधार 2 का उपयोग करता है, लेकिन सरल मॉडल प्लांटज़ में, वह स्पष्टता के लिए बेस 10 का उपयोग करता है। एक प्रणाली की कल्पना करें जहां मंथिसा के लिए भंडारण के दो पदों का उपयोग किया जाता है, एक स्थिति का उपयोग एक्सपोनेंट * (0 प्रतिनिधित्व + और 1 प्रतिनिधित्व -) के संकेत के लिए किया जाता है, और एक स्थिति एक्सपोनेंट के लिए उपयोग की जाती है। अब 0.93 और 0.91 जोड़ें। जवाब 1.8 है, 1.84 नहीं।

9311 0.93 या 9.3 बार 10 को -1 का प्रतिनिधित्व करता है।

9111 -1 में 0.91, या 9.1 बार 10 का प्रतिनिधित्व करता है।

सटीक उत्तर 1.84, या 1.84 गुणा 10 से 0 है, जो कि हमारे पास 5 पदों के साथ 18400 होगा, लेकिन केवल चार पदों के साथ, उत्तर 1800 है, या शून्य से 1.8 गुना 10, या 1.8 । बेशक, फ्लोटिंग पॉइंट डेटा प्रकार भंडारण के चार से अधिक पदों का उपयोग कर सकते हैं, लेकिन पदों की संख्या अभी भी सीमित है।

न केवल अंतरिक्ष द्वारा सीमित परिशुद्धता है, लेकिन "बाइनरी में आंशिक मूल्यों का सटीक प्रतिनिधित्व दो की व्यस्त शक्तियों तक सीमित है।" (प्लांटज़, ओप। सीआईटी।)।

0,11100110 (बाइनरी) = 0.८,९८,४३,७५० (दशमलव)

0,11100111 (बाइनरी) = 0.९,०२,३४,३७५ (दशमलव)

बाइनरी में 0.9 दशमलव के कोई सटीक प्रतिनिधित्व नहीं है। यहां तक ​​कि अधिक जगहों पर अंश लेना भी काम नहीं करता है, क्योंकि आप हमेशा के लिए 1100 दोहराते हैं।

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

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

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