2010-07-12 10 views
11

युगल का उपयोग करते समय मॉड्यूलस ऑपरेटर के साथ आप जावा के अजीब व्यवहार से कैसे निपटते हैं?जावा में युगल के साथ मॉड्यूलस

उदाहरण के लिए, आप उम्मीद करेंगे 3.9 - (3.9 % 0.1) का परिणाम 3.9 होने के लिए (और वास्तव में, Google कहते हैं कि मैं पागल नहीं जा रहा हूँ), लेकिन जब मैं जावा में इसे चलाने मैं 3.8000000000000003 मिलता है।

मुझे समझ में आता है कि जावा स्टोर्स और प्रक्रियाओं को कैसे दोगुना करता है, लेकिन क्या इसके आसपास काम करने का कोई तरीका है?

+1

तुम क्या करने कोशिश कर रहे हैं:

आप इस सवाल का जवाब आप Math.IEEEremainder का उपयोग कर उम्मीद कर सकते हैं? मुझे एहसास है कि आपको वास्तव में '%' की आवश्यकता नहीं है। – polygenelubricants

उत्तर

15

एक सटीक प्रकार का प्रयोग करें आप एक सटीक परिणाम की जरूरत है:

double val = 3.9 - (3.9 % 0.1); 
    System.out.println(val); // 3.8000000000000003 

    BigDecimal x = new BigDecimal("3.9"); 
    BigDecimal bdVal = x.subtract(x.remainder(new BigDecimal("0.1"))); 
    System.out.println(bdVal); // 3.9 

क्यों 3.8000 ... 003? चूंकि जावा परिणाम की गणना करने के लिए एफपीयू का उपयोग करता है। 3.9 आईईईई डबल परिशुद्धता नोटेशन में बिल्कुल स्टोर करना असंभव है, इसलिए यह 3.8 99 99 स्टोर करता है ... इसके बजाए। और 3.8 999% 0.01 0.0 99 99 देता है ... इसलिए परिणाम 3.8 से थोड़ा बड़ा है।

+0

+1 मुझे आईईईई फ्लोटिंग पॉइंट नंबरों के साथ मेरी इलेक्ट्रिकल इंजीनियरिंग कक्षा में हाथ से काम करने से नफरत है, लेकिन यह इसके लायक था। –

+0

धन्यवाद, यह अच्छी तरह से करेगा। – Andy

+0

अच्छा जवाब। तो एफपीयू यह समझने में सक्षम क्यों है कि ((3.9 डी/0.1 डी)% 1 डी) = 0।0' (मूल रूप से एक ही समस्या थोड़ा पुन: संगठित) जब राउंड ऑफ त्रुटि के कारण यह '(3.9 डी% 0.1 डी) = 0.0 99 99 99 99 99 99 997' लगता है? –

1

यदि आप जानते हैं कि आप कितने दशमलव का सामना कर रहे हैं, तो आप पहले पूर्णांक में कनवर्ट करने का प्रयास कर सकते हैं। यह फ्लोटिंग पॉइंट इनकुरेंसी की क्लासिक केस है। इसके बजाय ऐसा करने का 3.9 % 0.1 आप आप java.math.BigDecimal और उसके विधि divideAndRemainder() की तरह इस्तेमाल कर सकते हैं 3.899 % 0.0999

+1

और Google दावा करेगा कि 3.9% 0.1 = -4.4408921 × 10-16 जो मॉड्यूलस के साथ काफी फिट नहीं है। – Stroboskop

2
The Java Language Specification से

:

एक फ्लोटिंग प्वाइंट शेष आपरेशन के रूप में % ऑपरेटर द्वारा गणना का परिणाम है कि शेष आपरेशन आईईईई 754 आईईईई द्वारा परिभाषित द्वारा उत्पादित के समान नहीं है 754 शेष ऑपरेशन को राउंडिंग डिवीजन से एक ट्रंकिंग डिवीजन से नहीं, और इसलिए व्यवहार सामान्य पूर्णांक शेष ऑपरेटर के समान नहीं है। इसके बजाय, जावा प्रोग्रामिंग भाषा एक तरह से के अनुरूप व्यवहार करने के लिए पूर्णांक शेष ऑपरेटर की कि चल बिन्दु आपरेशनों पर% परिभाषित करता है; इसकी तुलना सी लाइब्रेरी फ़ंक्शन fmod से की जा सकती है। आईईईई 754 शेष ऑपरेशन लाइब्रेरी दिनचर्या गणित द्वारा गणना की गई है। IEEEremainder।

दूसरे शब्दों में, इस तथ्य यह है कि जावा शेष कंप्यूटिंग में शामिल विभाजन का परिणाम दौर है, जबकि IEEE754 डिवीजन के जवाब छोटा निर्दिष्ट के कारण है। यह विशेष मामला इस अंतर को स्पष्ट रूप से बेनकाब करने लगता है।

System.out.println(3.9 - (3.9 % 0.1)); 
System.out.println(3.9 - Math.IEEEremainder(3.9, 0.1)); 
संबंधित मुद्दे