BigDecimal - नए या valueOf का उपयोग करने के लिए


97

मुझे BigDecimal ऑब्जेक्ट को डबल d से बाहर निकालने के दो तरीके सामने आए।

1. new BigDecimal(d)
2. BigDecimal.valueOf(d)

कौन सा बेहतर तरीका होगा? क्या कोई नई वस्तु बनाएगा?

सामान्य तौर पर (न सिर्फ बिगडेसिमल), क्या अनुशंसित है - नया या मान?

धन्यवाद।


9
सामान्य तौर पर, valueOf को प्राथमिकता दी जाती है (क्योंकि यह "लोकप्रिय" उदाहरणों का पुन: उपयोग करके नई वस्तुओं को बनाने से बच सकता है), लेकिन बिगडेकिमल्स और डबल के मामले में, दुर्भाग्य से, दो विधियां अलग-अलग परिणाम उत्पन्न करती हैं, इसलिए आपको यह चुनना होगा कि आपको किसकी आवश्यकता है।
थिलो

जवाबों:


160

वे दो अलग-अलग प्रश्न हैं: "मुझे किसके लिए उपयोग करना चाहिए BigDecimal?" और "मैं सामान्य रूप से क्या करूँ?"

के लिए BigDecimal: यह थोड़ा मुश्किल है, क्योंकि वे एक ही काम नहीं करते हैं । वस्तु को तात्कालिक करने के लिए पारित मूल्य BigDecimal.valueOf(double)के विहित Stringप्रतिनिधित्व का उपयोग करेगा । दूसरे शब्दों में: वस्तु का मूल्य वही होगा जो आप देखते हैं ।doubleBigDecimalBigDecimalSystem.out.println(d)

यदि आप new BigDecimal(d)फिर भी उपयोग करते हैं , तो यथासंभव मूल्य का सहीBigDecimal प्रतिनिधित्व करने का प्रयास करेंगे । यह आमतौर पर बहुत अधिक अंकों में संग्रहीत किया जाएगा जो आप चाहते हैं। कड़ाई से बोलना, यह अधिक सही है , लेकिन यह बहुत कम सहज है।doublevalueOf()

JavaDoc में इसका एक अच्छा विवरण है:

इस निर्माता के परिणाम कुछ अप्रत्याशित हो सकते हैं। कोई यह मान सकता है कि new BigDecimal(0.1)जावा में लिखना एक ऐसा है BigDecimalजो 0.1 के बराबर है (1 का एक बिना मूल्य का मान, 1 के पैमाने के साथ), लेकिन यह वास्तव में 0.100000000000000005551115123125782702118158404041015625 के बराबर है। ऐसा इसलिए है क्योंकि 0.1 का प्रतिनिधित्व बिल्कुल नहीं किया जा सकता है double(या, उस मामले के लिए, किसी भी परिमित लंबाई के बाइनरी अंश के रूप में)। इस प्रकार, जो मान कंस्ट्रक्टर में पास किया जा रहा है, वह 0.1 के बराबर नहीं है, इसके बावजूद उपस्थिति नहीं है।

सामान्य तौर पर, यदि परिणाम समान है (यानी के मामले में नहीं BigDecimal, लेकिन अधिकांश अन्य मामलों में), तो valueOf()प्राथमिकता दी जानी चाहिए: यह सामान्य मूल्यों की कैशिंग कर सकता है (जैसा कि देखा गया है Integer.valueOf()) और यह बिना कैशिंग व्यवहार को भी बदल सकता है फोन करने वाले को बदलना होगा। हमेशा एक नया मान तुरंत newहोगा , भले ही आवश्यक न हो (सर्वोत्तम उदाहरण: बनाम )।new Boolean(true)Boolean.valueOf(true)


यह मेरा प्रश्न भी बताता है: stackoverflow.com/questions/15685705/…
क्रिश्चियन

3
@ जोशिम, यह स्पष्ट नहीं था। है new BigDecimal()की तुलना में बेहतर BigDecimal.valueOf()?
22

5
@ गुरुभक्ति: अगर एक जहां दूसरे से सख्ती से बेहतर है तो दोनों की कोई जरूरत नहीं होगी और मेरा जवाब बहुत कम होगा। वे एक ही काम नहीं करते हैं, इसलिए आप उन्हें उस तरह से रैंक नहीं कर सकते।
जोआचिम सॉउर

2
@JoachimSauer, ठीक है मुझे खेद है कि मुझे और अधिक विशिष्ट होना चाहिए था। क्या आप इस बात का उदाहरण देना चाहेंगे कि कब new BigDecimal()प्राथमिकता दी जाएगी और कब BigDecimal.valueOf()प्राथमिकता दी जाएगी?
अक्टूबर को २३:३३ पर पुनर्वसु

@ गुरुत्वाकर्षण: के परिणामों की तुलना करें new BigDecimal(1.0/30.0);और BigDecimal.valueOf(1.0/30.0)। देखें कि कौन सा परिणाम वास्तव में संख्यात्मक अंश 1/30 के करीब है।
supercat

46

यदि आप अपनी BigDecimalवस्तुओं का उपयोग मुद्रा मूल्यों को संग्रहीत करने के लिए कर रहे हैं , तो मैं दृढ़ता से सलाह देता हूं कि आप उनकी गणना में कहीं भी दोहरे मूल्यों को शामिल न करें

जैसा कि एक अन्य उत्तर में कहा गया है, दोहरे मूल्यों के साथ ज्ञात सटीकता के मुद्दे हैं और ये आपको बड़े समय के लिए वापस आएंगे।

एक बार जब आप अतीत से जुड़ जाते हैं, तो आपके प्रश्न का उत्तर सरल है। हमेशा स्ट्रिंगर मान के साथ कंस्ट्रक्टर विधि का उपयोग करें, क्योंकि कंस्ट्रक्टर के पास कोई तर्क नहीं valueOfहै String

यदि आप प्रमाण चाहते हैं, तो निम्नलिखित प्रयास करें:

BigDecimal bd1 = new BigDecimal(0.01);
BigDecimal bd2 = new BigDecimal("0.01");
System.out.println("bd1 = " + bd1);
System.out.println("bd2 = " + bd2);

आपको निम्न आउटपुट मिलेगा:

bd1 = 0.01000000000000000020816681711721685132943093776702880859375
bd2 = 0.01

इससे संबंधित प्रश्न भी देखें


5

मूल रूप से valueOf (डबल वैल) बस यही करता है:

return new BigDecimal(Double.toString(val));

इसलिए -> हां, एक नई वस्तु बनाई जाएगी :)।

सामान्य तौर पर मुझे लगता है कि यह आपकी कोडिंग शैली पर निर्भर करता है। मैं valueOf और "new" को मिक्स नहीं करूंगा, अगर दोनों एक ही परिणाम हैं।


7
तकनीकी रूप से सच है, लेकिन : यह बहुत बड़ा बदलाव लाएगा। valueOf()अधिक सहज व्यवहार है, जबकि new BigDecimal(d)अधिक सही है। दोनों का प्रयास करें और अंतर देखें।
जोकिम सॉर

तकनीकी रूप से झूठा है। 'new' हमेशा कीवर्ड हमेशा एक नई ऑब्जेक्ट बनाता है जबकि javadoc यह नहीं बताता है कि valueOf हमेशा एक नई ऑब्जेक्ट लौटाएगा या नहीं। यह हमेशा नहीं होता है। कैश में इसके कुछ मूल्य हैं, new BigDecimal(1) != new BigDecimal(1)लेकिनBigDecimal.valueOf(1) == BigDecimal.valueOf(1)
अकाल

1
@user: हाँ, लेकिन जब से BigDecimalअपरिवर्तनीय है यह एक ही तरीका है कि आदिम रैपर (व्यवहार किया जाना चाहिए Integer, Byte, ...) और Stringवस्तु पहचान: इलाज कर रहे हैं बात नहीं करनी चाहिए कि आपके कोड में, केवल मूल्य फर्क करना चाहिए।
जोकिम सॉउर

@ जोकिम राइट लेकिन एक कारण से वह आंतरिक कैश है। BigDecimal के बहुत सारे समान उदाहरणों की आवश्यकता नहीं है। और मैं डॉ को जवाब दे रहा था, उन्होंने कहा "एक नई वस्तु बनाई जाएगी"
अलकु २५'११ को .:४ to

3
@user: हाँ, यही कारण है कि मैंने कहा कि आम तौर पर पसंद किया valueOf()जाना चाहिए । लेकिन ध्यान दें कि कोई कैशिंग नहीं करता है (और यह शायद इसके लायक नहीं होगा, या तो)। BigDecimal.valueOf(double)
जोकिम सॉउर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.