फ्लोट की अशुद्धि के कारण असमानता


15

कम से कम जावा में, अगर मैं यह कोड लिखता हूं:

float a = 1000.0F;
float b = 0.00004F;
float c = a + b + b;
float d = b + b + a;
boolean e = c == d;

का मूल्य होगा । मेरा मानना ​​है कि यह इस तथ्य के कारण है कि फ्लोट सही संख्या का प्रतिनिधित्व करने के तरीके में बहुत सीमित हैं। लेकिन मुझे समझ में नहीं आता है कि सिर्फ की स्थिति को बदलने से यह असमानता क्यों हो सकती है।efalsea

मैंने नीचे पंक्ति 3 और 4 दोनों में से एक को s को कम कर दिया है , हालांकि का मान हो जाता :e t r u ebetrue

float a = 1000.0F;
float b = 0.00004F;
float c = a + b;
float d = b + a;
boolean e = c == d;

लाइन 3 और 4 में वास्तव में क्या हुआ? फ़्लोट्स के साथ संचालन क्यों सहयोगी नहीं हैं?

अग्रिम में धन्यवाद।


16
अपने उदाहरण से पता चलता है के रूप में, चल बिन्दु अलावा है विनिमेय। लेकिन यह साहचर्य नहीं है।
युवल फिल्मस

1
मैं आपको मूल परिभाषाओं को देखने के लिए प्रोत्साहित करता हूं। यह भी ध्यान दें कि कंपाइलर as ( r + s ) + t (बाईं ओर सहयोगी)। r+s+t(r+s)+t
युवल फिल्मस

2
यह देखने का एक आसान तरीका के लिए कि ऐसा क्यों होना चाहिए, Xएक बहुत बड़ी संख्या और Yएक बहुत छोटी संख्या पर विचार करें, जैसे कि X + Y = X। यहां, X + Y + -Xशून्य होगा। लेकिन X + -X + Yहोगा Y
डेविड श्वार्ट्ज


जवाबों:


20

सामान्य फ़्लोटिंग पॉइंट कार्यान्वयन में, एकल ऑपरेशन का परिणाम उत्पन्न होता है जैसे कि ऑपरेशन को अनंत परिशुद्धता के साथ किया गया था, और फिर निकटतम फ़्लोटिंग-पॉइंट नंबर पर गोल किया गया।

की तुलना और + एक : अनंत परिशुद्धता के साथ प्रदर्शन प्रत्येक ऑपरेशन का परिणाम एक ही है, इसलिए इन समान अनंत सटीक परिणाम एक समान तरीके से गोल कर रहे हैं। दूसरे शब्दों में, फ्लोटिंग-पॉइंट जोड़ सराहनीय है।a+bb+a

टेक : एक फ्लोटिंग प्वाइंट संख्या है। साथ द्विआधारी चल बिन्दु संख्या, 2 भी एक फ्लोटिंग प्वाइंट नंबर (प्रतिपादक एक करके बड़ा है), इसलिए है + किसी भी गोलाई त्रुटि के बिना जोड़ा जाता है। फिर a को सटीक मान b + b में जोड़ा जाता है । परिणाम सटीक मान 2 बी + ए है , जो निकटतम फ्लोटिंग-पॉइंट नंबर पर गोल है।b+b+ab2bb+bab+b2b+a

लो : एक + जोड़ा जाता है, और एक गोलाई त्रुटि होगी आर , तो हम परिणाम प्राप्त एक + + आरबी जोड़ें , और परिणाम सटीक मान 2 बी + + आर है , जो निकटतम फ्लोटिंग-पॉइंट नंबर पर गोल है।a+b+ba+bra+b+rb2b+a+r

तो एक मामले में, , गोल। दूसरे मामले में, 2 बी + + आर , गोल।2b+a2b+a+r

पुनश्च। दो विशेष संख्याओं के लिए और बी दोनों गणना एक ही परिणाम देती हैं या नहीं यह संख्याओं पर निर्भर करता है, और गणना में + बी में गोल त्रुटि पर , और आमतौर पर भविष्यवाणी करना मुश्किल है। एकल या दोहरी परिशुद्धता का उपयोग करने से सिद्धांत में समस्या पर कोई फर्क नहीं पड़ता है, लेकिन चूंकि गोलाई की त्रुटियां अलग-अलग होती हैं, इसलिए a और b के मान होंगे जहां एकल परिशुद्धता में परिणाम बराबर होते हैं और दोहरी सटीकता में वे नहीं होते हैं, या इसके विपरीत। परिशुद्धता बहुत अधिक होगी, लेकिन समस्या यह है कि दो अभिव्यक्ति गणितीय रूप से समान हैं लेकिन फ्लोटिंग-पॉइंट अंकगणित में समान नहीं हैं।aba+b

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

PPPS। एक टिप्पणी में पूछा गया है कि क्या हमें यह पूछना चाहिए कि फ्लोटिंग पॉइंट नंबर समान हैं या नहीं। बिल्कुल अगर आप जानते हैं कि आप क्या कर रहे हैं। उदाहरण के लिए, यदि आप एक सरणी को सॉर्ट करते हैं, या एक सेट को लागू करते हैं, तो आप अपने आप को भयानक परेशानी में डालते हैं यदि आप "लगभग बराबर" की कुछ धारणा का उपयोग करना चाहते हैं। एक ग्राफिकल यूजर इंटरफेस में, आपको ऑब्जेक्ट के आकारों को पुनर्गणना करने की आवश्यकता हो सकती है यदि किसी ऑब्जेक्ट का आकार बदल गया है - आप उस पुनर्गणना से बचने के लिए पुरानेसाइज == को नया आकार दें, यह जानते हुए कि व्यवहार में आपके पास लगभग समान आकार कभी नहीं हैं, और आपका प्रोग्राम सही है भले ही एक अनैच्छिक पुनर्वितरण हो।


इस विशेष मामले में, द्विआधारी में परिवर्तित होने पर बी आवधिक हो जाता है, इसलिए हर जगह गोलाई की त्रुटियां होती हैं।
एंड्रे सूजा लेमोस

1
@ AndréSouzaLemos bइस उत्तर में 0.00004 नहीं है, यह आपको रूपांतरण और गोलाई के बाद मिलता है ।
एलेक्सी रोमानोव

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

भोला सवाल: क्या फ्लोट समानता के लिए परीक्षण कभी समझ में आता है? अधिकांश प्रोग्रामिंग भाषाएं एए == बी परीक्षण की अनुमति क्यों देती हैं जहां दोनों एक या एक फ्लोट है?
जिज्ञासु_कैट

विकिपीडिया से प्रासंगिक परिभाषा: " मशीन एप्सिलॉन अस्थायी बिंदु अंकगणित में गोलाई के कारण सापेक्ष त्रुटि पर एक ऊपरी बाध्य देता है।"
ब्लैकहॉक 16

5

कंप्यूटर द्वारा समर्थित बाइनरी फ्लोटिंग पॉइंट प्रारूप अनिवार्य रूप से मनुष्यों द्वारा उपयोग किए जाने वाले दशमलव वैज्ञानिक संकेतन के समान है।

फ्लोटिंग-पॉइंट नंबर में एक चिन्ह, मंटिसा (निश्चित चौड़ाई), और घातांक (निश्चित चौड़ाई) होते हैं, जैसे:

+/-  1.0101010101 × 2^12345
sign   ^mantissa^     ^exp^

नियमित वैज्ञानिक संकेतन का एक समान प्रारूप है:

+/- 1.23456 × 10^99

यदि हम परिमित परिशुद्धता के साथ वैज्ञानिक संकेतन में करते हैं, प्रत्येक ऑपरेशन के बाद गोलाई, तो हमें बाइनरी फ्लोटिंग पॉइंट के समान सभी बुरे प्रभाव मिलते हैं।


उदाहरण

उदाहरण के लिए, मान लें कि हम दशमलव बिंदु के बाद ठीक 3 अंकों का उपयोग करते हैं।

a = 99990 = 9.999 × 10^4
b =     3 = 3.000 × 10^0

(a + b) + b

अब हम गणना करते हैं:

c = a + b
  = 99990 + 3      (exact)
  = 99993          (exact)
  = 9.9993 × 10^4  (exact)
  = 9.999 × 10^4.  (rounded to nearest)

अगले चरण में:

d = c + b
  = 99990 + 3 = ...
  = 9.999 × 10^4.  (rounded to nearest)

इसलिए (a + b) + b = 9.999 × 10 4

(b + b) + a

लेकिन अगर हमने ऑपरेशन एक अलग क्रम में किया है:

e = b + b
  = 3 + 3  (exact)
  = 6      (exact)
  = 6.000 × 10^0.  (rounded to nearest)

आगे हम गणना करते हैं:

f = e + a
  = 6 + 99990      (exact)
  = 99996          (exact)
  = 9.9996 × 10^4  (exact)
  = 1.000 × 10^5.  (rounded to nearest)

इसलिए (b + b) + a = 1.000 × 10 5 , जो हमारे अन्य उत्तर से अलग है।


5

जावा IEEE 754 बाइनरी फ्लोटिंग पॉइंट प्रतिनिधित्व का उपयोग करता है, जो 23 बाइनरी अंकों को मंटिसा को समर्पित करता है, जिसे पहले महत्वपूर्ण अंक (अंतरिक्ष को बचाने के लिए छोड़ा गया) के साथ शुरू करने के लिए सामान्यीकृत किया जाता है।

0.0000410=0.00000000000000101001111100010110101100010001110001101101000111...2=[1.]01001111100010110101100010001110001101101000111...2×215

100010+0.0000410=1111101000.00000000000000101001111100010110101100010001110001101101000111...2=[1.]11110100000000000000000101001111100010110101100010001110001101101000111...2×29

लाल रंग के हिस्से मंटिस हैं, क्योंकि वे वास्तव में प्रतिनिधित्व करते हैं (गोलाई से पहले)।

(100010+0.0000410)+0.0000410(0.0000410+0.0000410)+100010


0

हम हाल ही में इसी तरह के एक दौर में चले गए। उपर्युक्त उत्तर सही हैं, हालांकि काफी तकनीकी हैं।

मैंने पाया कि निम्नलिखित में एक अच्छी व्याख्या है कि गोलाई की त्रुटियाँ क्यों हैं। http://csharpindepth.com/Articles/General/FloatingPoint.aspx

TLDR: बाइनरी फ़्लोटिंग पॉइंट्स को दशमलव फ़्लोटिंग पॉइंट्स पर सटीक रूप से मैप नहीं किया जा सकता है। यह उन अशुद्धियों का कारण बनता है जो गणितीय कार्यों के दौरान मिश्रित हो सकते हैं।

दशमलव फ़्लोटिंग संख्याओं का उपयोग करने वाला एक उदाहरण: 1/3 + 1/3 + 1/3 सामान्य रूप से 1. के बराबर होगा। हालांकि, दशमलव में: 0.333333 + 0.333333 + 0.333333 कभी भी 1.000000 के बराबर नहीं होता है

बाइनरी डिकिमल्स पर गणितीय संचालन करते समय भी ऐसा ही होता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.