2017-09-11 6 views
5

मैं उलझन में हूँ। अगर मैंDoubleStream.sum() का परिणाम सीधे जोड़ से अलग क्यों होता है?

System.out.println(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1); 

की गणना करता हूं तो मुझे 0.9999999999999999 का परिणाम मिलता है। लेकिन अगर मैं

Double sum = DoubleStream.builder().add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).add(0.1).build().sum(); 
System.out.println(sum); 

फिर गणना मैं 1.0 का एक परिणाम मिलता है। कोई अंतर क्यों है?

+2

संबंधित: https://stackoverflow.com/questions/588004/is-floating-point-math-broken – GhostCat

+3

और ध्यान रखें: पहली पंक्ति है ** पूरी तरह से * * संकलक द्वारा गणना की। यह लगातार फोल्डिंग करता है और आपके लिए इन मानों को जोड़ता है। अपने बाइट कोड की जांच करें - आपको विकल्प 1 के लिए वहां कोई अतिरिक्त नहीं मिलेगा। – GhostCat

+2

@GostCat यह अभी भी एक अच्छा सवाल है। हां, फ्लोटिंग पॉइंट गणित अतुलनीय है, लेकिन यह लगातार होना चाहिए। यह यादृच्छिक नहीं है। क्या अंतर बताता है? –

उत्तर

10

double java.util.stream.DoubleStream.sum() की जावाडोक आपके प्रश्न के उत्तर:

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

दूसरे शब्दों में, sum() के कार्यान्वयन (के रूप में आप अपने पहले स्निपेट में देखा, सटीकता मुद्दों हो सकता है) डबल मूल्यों का सरल योग उपयोग करने के लिए नहीं है, और इसलिए एक more accurate result वापस आ सकते हैं।

संपादित करें: ध्यान दें कि DoubleStream का sum() का उपयोग करने के बावजूद एक और सटीक परिणाम देने के लिए प्रतीत होता है, यह एक कार्यान्वयन विस्तार है, इसलिए यह जावाडोक द्वारा गारंटी नहीं है। इसके अलावा, सरल double अतिरिक्त अधिक कुशल है, क्योंकि इसमें DoubleStream बनाने का ऊपरी भाग नहीं है। आपको यह तय करना होगा कि क्या आप संभावित बेहतर सटीकता या प्रदर्शन पसंद करते हैं।

+0

मुझे लगता है कि यह उद्धरण के लिए "बोल्ड" करने के लिए उपयोगी होगा; यह महत्वपूर्ण बिंदु – fge

+1

@fge मुझे लगता है कि संपूर्ण उद्धरण (या इसमें से अधिकांश) प्रासंगिक है, इसलिए मैंने इसे किसी भी बोल्ड में नहीं रखा है। वैसे भी यह एक छोटा सा उद्धरण है। – Eran

+0

हां, पूरा उद्धरण प्रासंगिक है, लेकिन आपको लगता है कि, "पहली नज़र में" जवाब पढ़ने पर, क्या पूरा उद्धरण याद किया जाएगा? आप जानते हैं कि कैसे मानव दिमाग wrt दृश्य सुराग और ध्यान अवधि काम करता है, है ना? :) विशेष रूप से जब javadoc लिंक पर क्लिक करने और पूरे javadoc_ पढ़ने के प्रतिबिंब के रूप में प्रचलित नहीं होगा। खैर, बस मेरी राय;) – fge

2

सिर्फ एरान के उत्तर को बढ़ाने के लिए, आंतरिक रूप से DoubleStream#sumKahan Summation का उपयोग करता है।

प्रासंगिक भागों:

/** 
* Incorporate a new double value using Kahan summation/
* compensation summation. 
* 
* High-order bits of the sum are in intermediateSum[0], low-order 
* bits of the sum are in intermediateSum[1], any additional 
* elements are application-specific. 
* 
*/ 
static double[] sumWithCompensation(double[] intermediateSum, double value) { .... 
संबंधित मुद्दे

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