मुझे कुछ फ्लोटिंग पॉइंट वैरिएबल की गणना करनी है और मेरे सहकर्मी ने मुझे BigDecimal
इसके बजाय उपयोग करने का सुझाव दिया है double
क्योंकि यह अधिक सटीक होगा। लेकिन मैं जानना चाहता हूं कि यह क्या है और सबसे अधिक कैसे बनाया जाए BigDecimal
?
मुझे कुछ फ्लोटिंग पॉइंट वैरिएबल की गणना करनी है और मेरे सहकर्मी ने मुझे BigDecimal
इसके बजाय उपयोग करने का सुझाव दिया है double
क्योंकि यह अधिक सटीक होगा। लेकिन मैं जानना चाहता हूं कि यह क्या है और सबसे अधिक कैसे बनाया जाए BigDecimal
?
जवाबों:
A BigDecimal
संख्याओं का प्रतिनिधित्व करने का एक सटीक तरीका है। A Double
की एक निश्चित सटीकता है। विभिन्न परिमाण (कहते हैं कि के युगल के साथ कार्य करना d1=1000.0
और d2=0.001
) परिणाम सकता है में 0.001
किया जा रहा है alltogether गिरा जब संक्षेप के रूप में परिमाण में अंतर इतना बड़ा है। इसके साथ BigDecimal
ऐसा नहीं होगा।
इसका नुकसान BigDecimal
यह है कि यह धीमा है, और एल्गोरिदम को उस तरह से प्रोग्राम करना थोड़ा मुश्किल है (कारण +
-
*
और /
अतिभारित नहीं होना)।
यदि आप पैसे के साथ काम कर रहे हैं, या सटीक होना चाहिए, उपयोग करें BigDecimal
। अन्यथा Doubles
काफी अच्छे हो जाते हैं।
मैं पढ़ सिफारिश करते हैं जावाडोक के BigDecimal
रूप में वे बातें बेहतर की तुलना में मैं यहाँ करने के लिए समझाने कर :)
if (Math.abs(loadPerServer - maxLoadPerServer) < 0.000001d) {
BigDecimal
", एक डबल में अधिक "सटीक" (अधिक अंक) होगा।
मेरी अंग्रेजी अच्छी नहीं है, इसलिए मैं यहां एक सरल उदाहरण लिखूंगा।
double a = 0.02;
double b = 0.03;
double c = b - a;
System.out.println(c);
BigDecimal _a = new BigDecimal("0.02");
BigDecimal _b = new BigDecimal("0.03");
BigDecimal _c = _b.subtract(_a);
System.out.println(_c);
कार्यक्रम का उत्पादन:
0.009999999999999998
0.01
कोई अभी भी डबल का उपयोग करना चाहते हैं? ;)
System.out.println(0.003f - 0.002f);
सटीक है:System.out.println(new BigDecimal("0.003").subtract(new BigDecimal("0.002")));
दोहरे से दो मुख्य अंतर हैं:
मौद्रिक गणना के लिए आपको बिगडेसिमल का उपयोग करने का कारण यह नहीं है कि यह किसी भी संख्या का प्रतिनिधित्व कर सकता है, लेकिन यह सभी संख्याओं का प्रतिनिधित्व कर सकता है जो दशमलव धारणा में प्रतिनिधित्व कर सकते हैं और इसमें मौद्रिक दुनिया में लगभग सभी संख्याएं शामिल हैं (आप कभी भी 1/3 $ स्थानांतरित नहीं करते हैं किसी को)।
यदि आप एक भिन्न मान लिखते हैं 1 / 7
जैसे दशमलव मान जो आपको मिलता है
1/7 = 0.142857142857142857142857142857142857142857...
के अनंत क्रम के साथ 142857
। चूंकि आप केवल अंकों की एक सीमित संख्या लिख सकते हैं, आप अनिवार्य रूप से एक गोलाई (या ट्रंकेशन) त्रुटि का परिचय देंगे।
एक भिन्नात्मक भाग के साथ द्विआधारी संख्याओं की तरह 1/10
या 1/100
व्यक्त की गई संख्याओं में दशमलव बिंदु के बाद अनंत संख्या में अंक भी होते हैं:
1/10 = binary 0.0001100110011001100110011001100110...
Doubles
मानों को बाइनरी के रूप में संग्रहीत करें और इसलिए किसी भी अंकगणित को किए बिना, केवल दशमलव संख्या को बाइनरी संख्या में परिवर्तित करके त्रुटि का परिचय दे सकते हैं।
दशमलव संख्या (जैसे BigDecimal
), दूसरी ओर, प्रत्येक दशमलव अंक को इस प्रकार संचित करें। इसका मतलब यह है कि एक दशमलव प्रकार एक सामान्य अर्थ में बाइनरी फ्लोटिंग पॉइंट या फिक्स्ड पॉइंट प्रकार से अधिक सटीक नहीं है (अर्थात यह 1/7
परिशुद्धता के नुकसान के बिना स्टोर नहीं कर सकता है ), लेकिन यह उन संख्याओं के लिए अधिक सटीक है जिनके पास दशमलव अंकों की एक सीमित संख्या है अक्सर पैसे की गणना के लिए मामला है।
जावा का BigDecimal
अतिरिक्त लाभ यह है कि इसमें दशमलव बिंदु के दोनों तरफ अंकों की एक मनमानी (लेकिन परिमित) संख्या हो सकती है, जो केवल उपलब्ध स्मृति द्वारा सीमित है।
BigDecimal Oracle की मनमानी-सटीक संख्यात्मक लाइब्रेरी है। बिगडेसीमल जावा भाषा का एक हिस्सा है और यह वित्तीय से लेकर वैज्ञानिक (यह वह जगह है, जहां पर विभिन्न प्रकार के अनुप्रयोगों के लिए उपयोगी है)।
कुछ गणनाओं के लिए युगल का उपयोग करने में कुछ भी गलत नहीं है। मान लीजिए, हालाँकि, आप Math.Pi * Math.Pi / 6 की गणना करना चाहते थे, अर्थात्, दो के वास्तविक तर्क के लिए रीमैन ज़ेटा फ़ंक्शन का मूल्य (एक परियोजना जो मैं वर्तमान में काम कर रहा हूं)। फ्लोटिंग-पॉइंट डिवीजन आपको राउंडिंग त्रुटि की एक दर्दनाक समस्या के साथ प्रस्तुत करता है।
दूसरी ओर बिगडेसीमल में मनमानी परिशुद्धता के लिए भावों की गणना के कई विकल्प शामिल हैं। BigDecimal Java वर्ल्ड में नीचे दिए गए ओरेकल डॉक्यूमेंटेशन में बताए गए तरीकों को जोड़ने, गुणा करने और विभाजित करने का तरीका +, *, और / लें।
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
तुलना विधि लूप में और उसके लिए विशेष रूप से उपयोगी है।
हालांकि, BigDecimal के लिए निर्माणकर्ताओं के अपने उपयोग में, सावधान रहें। स्ट्रिंग कंस्ट्रक्टर कई मामलों में बहुत उपयोगी है। उदाहरण के लिए, कोड
बिगडेसीमल ऑनथर्ड = नया बिगडेसीमल ("0.33333333333");
सटीकता की एक निर्दिष्ट डिग्री के लिए असीम-दोहराव संख्या का प्रतिनिधित्व करने के लिए 1/3 के एक स्ट्रिंग प्रतिनिधित्व का उपयोग करता है। राउंड-ऑफ त्रुटि JVM के अंदर कहीं अधिक गहरी होने की संभावना है कि राउंड-ऑफ त्रुटियां आपके अधिकांश व्यावहारिक गणनाओं को परेशान नहीं करेंगी। हालांकि, व्यक्तिगत अनुभव से, मैंने राउंड-ऑफ रेंगना देखा है, हालांकि। सेटस्ले विधि इन संदर्भों में महत्वपूर्ण है, जैसा कि ओरेकल दस्तावेज से देखा जा सकता है।
/* * Portions Copyright IBM Corporation, 2001. All Rights Reserved. */
यदि आप गणना के साथ काम कर रहे हैं, तो इस पर कानून हैं कि आपको कैसे गणना करनी चाहिए और आपको किस सटीकता का उपयोग करना चाहिए। यदि आप असफल होते हैं कि आप कुछ अवैध कर रहे हैं। एकमात्र वास्तविक कारण यह है कि दशमलव मामलों का बिट प्रतिनिधित्व सटीक नहीं है। जैसा कि तुलसी ने कहा है, एक उदाहरण सबसे अच्छा स्पष्टीकरण है। बस अपने उदाहरण के पूरक के लिए, यहाँ क्या होता है:
static void theDoubleProblem1() {
double d1 = 0.3;
double d2 = 0.2;
System.out.println("Double:\t 0,3 - 0,2 = " + (d1 - d2));
float f1 = 0.3f;
float f2 = 0.2f;
System.out.println("Float:\t 0,3 - 0,2 = " + (f1 - f2));
BigDecimal bd1 = new BigDecimal("0.3");
BigDecimal bd2 = new BigDecimal("0.2");
System.out.println("BigDec:\t 0,3 - 0,2 = " + (bd1.subtract(bd2)));
}
आउटपुट:
Double: 0,3 - 0,2 = 0.09999999999999998
Float: 0,3 - 0,2 = 0.10000001
BigDec: 0,3 - 0,2 = 0.1
इसके अलावा हमारे पास है:
static void theDoubleProblem2() {
double d1 = 10;
double d2 = 3;
System.out.println("Double:\t 10 / 3 = " + (d1 / d2));
float f1 = 10f;
float f2 = 3f;
System.out.println("Float:\t 10 / 3 = " + (f1 / f2));
// Exception!
BigDecimal bd3 = new BigDecimal("10");
BigDecimal bd4 = new BigDecimal("3");
System.out.println("BigDec:\t 10 / 3 = " + (bd3.divide(bd4)));
}
हमें आउटपुट देता है:
Double: 10 / 3 = 3.3333333333333335
Float: 10 / 3 = 3.3333333
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion
परंतु:
static void theDoubleProblem2() {
BigDecimal bd3 = new BigDecimal("10");
BigDecimal bd4 = new BigDecimal("3");
System.out.println("BigDec:\t 10 / 3 = " + (bd3.divide(bd4, 4, BigDecimal.ROUND_HALF_UP)));
}
आउटपुट है:
BigDec: 10 / 3 = 3.3333