2011-01-12 29 views
12

क्या कोई यहां कृपया मुझे यह समझने में सहायता कर सकता है कि फ़्लोटिंग पॉइंट सीमाएं आपकी गणनाओं में त्रुटियों का कारण बनती हैं। उदाहरण के लिए निम्नलिखित कोड।फ़्लोटिंग पॉइंट समस्याओं को समझना

CalculateTotalTax = function (TaxRate, TaxFreePrice) { 
    return ((parseFloat(TaxFreePrice)/100) * parseFloat(TaxRate)).toFixed(4); 
}; 

मैं इस विधि के लिए गलत परिणाम के कारण होने वाले किसी भी दो मूल्यों को इनपुट करने में असमर्थ रहा हूं। अगर मैं फिक्स्ड (4) को हटा देता हूं तो मैं देख सकता हूं कि गणना सटीकता खोने के लिए कहां शुरू होती है (कहीं 6 वें दशमलव स्थान के आसपास)। ऐसा कहकर कि, फ्लोट की मेरी समझ यह है कि यहां तक ​​कि छोटी संख्याएं कभी-कभी प्रतिनिधित्व करने में असफल हो सकती हैं या मैंने गलत समझा है और 4 दशमलव स्थान (उदाहरण के लिए) हमेशा सटीक रूप से प्रदर्शित किया जा सकता है।

MSDN such के रूप में तैरता बताते हैं ...

इसका मतलब यह है कि वे किसी भी मात्रा कि प्रपत्र क/ (2^n के एक द्विआधारी अंश (नहीं है की एक सटीक प्रतिनिधित्व धारण नहीं कर सकता) जहां के और एन पूर्णांक हैं)

अब मुझे लगता है कि यह सभी फ्लोट्स पर लागू होता है (जावास्क्रिप्ट में उपयोग किए गए लोगों को शामिल करना)।

मूल रूप से मेरा प्रश्न इस पर उबाल जाता है। कोई यह कैसे निर्धारित कर सकता है कि फ़्लोटिंग पॉइंट ऑपरेशंस में त्रुटियों के लिए कोई विशिष्ट विधि कमजोर होगी, उन त्रुटियों को किस प्रकार सटीक किया जाएगा और उन त्रुटियों को उत्पन्न करने के लिए किन इनपुटों की आवश्यकता होगी?

उम्मीद है कि मैं जो पूछ रहा हूं वह समझ में आता है।

+0

शायद यह इस विषय से संबंधित है: http://en.wikipedia.org/wiki/Machine_epsilon –

+0

* टोनी द टट्टू *, जिसे [जॉन स्कीट] भी कहा जाता है (http://stackoverflow.com/users/22656/जॉन-स्कीट), एक [उत्कृष्ट स्पष्टीकरण] है (http://codeblog.jonskeet.uk/2009/11/02/omg-ponies-aka-humanity-epic-fail/)। परेशान किए बिना पढ़ने योग्य, स्पष्ट, हास्यास्पद, और [कुछ लिंक] के रूप में भारी नहीं (http://docs.sun.com/source/806-3568/ncg_goldberg.html) जिन्हें अक्सर इस विषय पर पोस्ट किया जाता है। – MarkJ

उत्तर

10

पढ़कर प्रारंभ हर कंप्यूटर वैज्ञानिक प्वाइंट फ्लोटिंग के बारे में क्या पता होना चाहिए: http://docs.sun.com/source/806-3568/ncg_goldberg.html

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

लेकिन यदि यह उच्च स्तर की सटीकता के साथ उत्तर प्राप्त करने के लिए पर्याप्त है, तो फ्लोट पर्याप्त रूप से पर्याप्त होना चाहिए, विशेष रूप से डबल परिशुद्धता।

1- आप machine epsilon के बारे में पता होना चाहिए:

4

दो महत्वपूर्ण बात यह है अब आप जब तैरता के साथ काम करना चाहिए रहे हैं। यह जानने के लिए कि आपके पास कितना सटीकता है।

2- आप if two values are equal in base 10, they are equal in base 2 in a machine with precision limit मानना ​​नहीं चाहिए।

if ((6.0/10.0)/3.0 != .2) { 
     cout << "gotcha" << endl; 
} 

संख्या 2 पर्याप्त कायल आप चल समानता के लिए बिन्दु संख्या की तुलना न करें बनाने के लिए हो सकता है, बजाय एक सीमा और अधिक से अधिक या ऑपरेटरों से कम की तुलना के लिए इस्तेमाल किया जा सकता

+1

संख्या 2 यह इंगित नहीं करता है कि आपको "समानता के लिए फ़्लोटिंग पॉइंट नंबरों की तुलना कभी नहीं करना चाहिए"; आखिरकार, यह आसानी से पालन करेगा कि आपको समानता के लिए दशमलव संख्याओं की तुलना कभी नहीं करना चाहिए। इसका मतलब है कि किसी को कोड नहीं लिखना चाहिए जिसे कोई समझ में नहीं आता है। फ्लोटिंग पॉइंट कैसे काम करता है यह जानने के लिए समय लें। –

+0

जैसा कि आपने कहा था कि किसी को फ़्लोटिंग पॉइंट सीखने में समय लगाना चाहिए; कुछ ऐसा (0.1 == 1/10) इतना निर्दोष दिखता है कि कोई भी शायद यह नहीं सोचता कि यह एक बग का कारण बन रहा है जब तक कि वह इसके बारे में पहले नहीं पढ़ता। गणित की मूल बातें के बारे में भी बात करते हुए, बहुत से लोग नहीं जानते कि 10 = 9.9 99 .... या दशमलव को बाइनरी में कैसे परिवर्तित करें। –

+1

कारण '.1! = 1/10' क्योंकि' 1/10 == 0' है। आप पूर्णांक विभाजन का उपयोग कर रहे हैं। –

1

नहीं है, की संख्या दशमलव स्थानों का प्रतिनिधित्व करने के लिए कुछ भी नहीं है।

कोशिश करें .1 * 3, या 162.295/10, या 24.0 + 47.98। जो जेएस में मेरे लिए असफल हो जाते हैं। लेकिन, 24.0 * 47.98 विफल नहीं है।

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

2

अन्य उत्तर इस समस्या को समझने के लिए अच्छे संसाधन की ओर इशारा किया है। अपने वास्तव में अपने कोड में मौद्रिक मूल्य का उपयोग कर (अपने उदाहरण के रूप में) आप दशमलव प्रकार (नेट में System.Decimal) को प्राथमिकता देनी चाहिए। ये फ्लोटिंग का उपयोग करने और डोमेन से बेहतर मिलान करने से कुछ गोल करने वाली समस्याओं से बचेंगे।

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