2012-08-14 38 views
58

मैं बिगडेसिमल के साथ एक साधारण गुणा कर रहा हूं और शून्य से गुणा करते समय मुझे कुछ अजीब व्यवहार मिल गया है (इस उपयोग-मामले में शून्य से गुणा करना सही है)।बिगडेसिमल शून्य से गुणा

बुनियादी गणित मुझे उस कुछ भी शून्य से गुणा शून्य के बराबर होगा बताता है (देखें: Zero Product Property और Multiplication Properties)

हालांकि, निम्नलिखित कोड लगातार एक ही त्रुटि के साथ विफल हो जाएगा:

assertEquals(new BigDecimal(0), new BigDecimal(22.3).multiply(new BigDecimal(0))); 
java.lang.AssertionError: 
Expected :0 
Actual :0E-48 

क्या यह बिगडिसीमल के साथ एक गलत है या क्या गणित की कुछ विशिष्ट शाखा है जिसे मैं कहीं याद कर रहा हूं?

नोट्स: JDK 1.6.0_27 इंटेलीजे 11

+3

हाँ संख्यात्मक विश्लेषण और विशेष रूप से सन्निकटन और काट-छांट त्रुटि –

+0

या 'double' में इस पर गौर आप 'assertEquals (0, 23.3 * 0, 0) लिख सकते हैं; '; –

+11

और' BigDecimal.ZERO' में भी देखें। – EJP

उत्तर

84

में चल रहे आप BigDecimals तुलना करने के लिए, इस दावे की तरह करता है equals() विधि का उपयोग नहीं कर सकते हैं। ऐसा इसलिए है क्योंकि यह बराबर कार्य स्केल की तुलना करेगा। यदि स्केल अलग है, equals() झूठी वापसी करेगा, भले ही वे गणितीय रूप से समान संख्या हों।

आप फिर भी तुम क्या चाहते करने के लिए compareTo() उपयोग कर सकते हैं: @assylias बताते

रूप में, आप भी new BigDecimal("22.3") निर्माता का उपयोग करना चाहिए डबल परिशुद्धता मुद्दों से बचने के।

BigDecimal expected = BigDecimal.ZERO; 
BigDecimal actual = new BigDecimal("22.3").multiply(BigDecimal.ZERO); 
assertEquals(0, expected.compareTo(actual)); 

वहाँ भी एक विधि signum() कहा जाता है, कि -1, 0 या 1 नकारात्मक के लिए, शून्य, और सकारात्मक दिखाए है।तो अगर आप भी शून्य के लिए

assertEquals(0, actual.signum()); 
20

equals()BigDecimal पर चेक के BigDecimal की आंतरिक स्थिति तुलना

के लिए परीक्षण कर सकते हैं नीचे

public boolean equals(Object x) { 
    if (!(x instanceof BigDecimal)) 
     return false; 
    BigDecimal xDec = (BigDecimal) x; 
    if (x == this) 
     return true; 
    if (scale != xDec.scale) 
     return false; 
    long s = this.intCompact; 
    long xs = xDec.intCompact; 
    if (s != INFLATED) { 
     if (xs == INFLATED) 
      xs = compactValFor(xDec.intVal); 
     return xs == s; 
    } else if (xs != INFLATED) 
     return xs == compactValFor(this.intVal); 

    return this.inflate().equals(xDec.inflate()); 
} 

कोड देखें अगर आप की तुलना करने के मूल्यों compareTo() उपयोग करना चाहते हैं

अपना कोड

पर बदलें
assertEquals(0 , new BigDecimal(0).compareTo(new BigDecimal(22.3).multiply(new BigDecimal(0))); 

अद्यतन:

उपयोग निर्माता स्ट्रिंग परिशुद्धता में सटीकता के लिए BigDecimal के लिए एक पैरामीटर के रूप लेने के लिए नीचे दिए गए


संबंधित लिंक की जाँच भी देखें

47

अपने कोड के साथ 2 समस्या नहीं है:

  • आप के रूप में अन्य उत्तर
  • ने सलाह दी, बराबर है के बजाय compareTo साथ BigDecimal की तुलना करनी चाहिए लेकिन आप यह भी होना चाहिए डबल परिशुद्धता के मुद्दों से बचने के लिए डबल कन्स्ट्रक्टर new BigDecimal(22.3) के बजाय स्ट्रिंग कन्स्ट्रक्टर का उपयोग करें: new BigDecimal("22.3")

दूसरे शब्दों में, निम्नलिखित कोड (जो सही ढंग से compareTo उपयोग करता है) अभी भी झूठे रिटर्न:

क्योंकि 0.1d * 10d != 1
BigDecimal bd = new BigDecimal(0.1).multiply(new BigDecimal(10)); 
System.out.println(bd.compareTo(BigDecimal.ONE) == 0); 

+0

कन्स्ट्रक्टर परिवर्तन – Richard

+0

@assylias "को इंगित करने के लिए धन्यवाद, लेकिन आपको डबल कन्स्ट्रक्टर मुद्दों का उपयोग करने के लिए डबल बिगडिसीमल (22.3) के बजाय डबल बिगडिसीमल (22.3") स्ट्रिंग कन्स्ट्रक्टर का उपयोग करना चाहिए। क्या आप डबल परिशुद्धता मुद्दे की व्याख्या कर सकते हैं? – Geek

+1

@Geek इस 'System.out.println (नया BigDecimal ("0.1")) आज़माएं;' और यह 'System.out.println (नया BigDecimal (0.1d)); '। पहला वाला (स्ट्रिंग कन्स्ट्रक्टर) प्रिंट करता है '0.1', जबकि दूसरा (डबल कन्स्ट्रक्टर) प्रिंट करता है' 0.1000000000000000055511151231257827021181583404541015625'। ऐसा इसलिए होता है क्योंकि एक डबल 0.1 का प्रतिनिधित्व नहीं कर सकता है। इसके बारे में अधिक [उदाहरण के लिए इस पृष्ठ पर] (http: // stackoverflow।com/प्रश्न/4937402/चलती दशमलव-स्थानों-दर-में-एक-डबल)। स्पष्टीकरण के लिए – assylias