यह दस्तावेज़ीकरण द्वारा विशेष रूप से अच्छी तरह से समझाया नहीं गया है, लेकिन Double.toString(double)
अनिवार्य रूप से उत्पादन के उत्पादन में कुछ गोल करता है। Double.toString
एल्गोरिदम का उपयोग पूरे जावा एसई में किया जाता है, उदाहरण सहित PrintStream.println(double)
System.out
। प्रलेखन इस कहते हैं:
कितने अंक मीटर या एक का आंशिक भाग के लिए मुद्रित किया जाना चाहिए? आंशिक भाग का प्रतिनिधित्व करने के लिए कम से कम एक अंक होना चाहिए, और इसके अलावा बहुत से, लेकिन केवल उतने ही अधिक अंक जितना अधिक अंक double
के आसन्न मूल्यों से तर्क मान को विशिष्ट रूप से अलग करने के लिए आवश्यक हैं। ऐसा लगता है कि x सटीक गणितीय मान है जो इस विधि द्वारा एक सीमित nonzero तर्क डी के लिए उत्पादित दशमलव प्रतिनिधित्व द्वारा दर्शाया गया है। फिर डीdouble
x के निकट double
मान होना चाहिए; या यदि दो double
मान समान रूप से एक्स, के करीब हैं तो घ उनमें से एक और घ significand0
होना चाहिए कम से कम महत्वपूर्ण बिट होना चाहिए।
दूसरे शब्दों में, यह कहता है कि toString
का वापसी मूल्य आवश्यक रूप से तर्क का सटीक दशमलव प्रतिनिधित्व नहीं है। एकमात्र गारंटी यह है कि (मोटे तौर पर बोलने) तर्क किसी अन्य double
मान की तुलना में वापसी मूल्य के करीब है।
तो जब आप System.out.println(1.10)
और 1.10
छपा है की तरह कुछ करते हैं, यह मतलब यह नहीं है में पारित मूल्य वास्तव में आधार 10 मूल्य 1.10
के बराबर है। बल्कि, अनिवार्य रूप से निम्न होता है:
- पहले, संकलन के दौरान, शाब्दिक
1.10
की जांच की और निकटतम double
मूल्य का उत्पादन करने के गोल है। (यह JLS here में कहते हैं इस के लिए नियम double
के लिए Double.valueOf(String)
में जैसे विस्तृत कर रहे हैं।)
- दूसरा, जब कार्यक्रम चलाता है,
Double.toString
कुछ दशमलव मान जो double
मूल्य पिछले चरण में उत्पादित करीब है की एक String
प्रतिनिधित्व का उत्पादन किसी भी अन्य double
मूल्य से अधिक।
यह सिर्फ इतना है कि दूसरे चरण में String
करने के लिए रूपांतरण अक्सर एक String
जो पहले चरण में शाब्दिक रूप में ही है पैदा करता है। मुझे लगता है कि यह डिजाइन द्वारा है। हालांकि, शाब्दिक उदा। 1.10
double
मान नहीं बनाता है जो 1.10
के बराबर है।
आप (क्योंकि वे हमेशा एक double
में फिट कर सकते हैं, या float
) एक double
के वास्तविक मूल्य की खोज कर सकते BigDecimal(double)
निर्माता का उपयोग कर:,
एक double
एक BigDecimal
के लिए एक स्रोत के रूप में इस्तेमाल किया जाना चाहिए जब ध्यान दें कि यह कन्स्ट्रक्टर एक सटीक रूपांतरण प्रदान करता है; यह Double.toString(double)
विधि का उपयोग करके को में परिवर्तित करने और फिर BigDecimal(String)
कन्स्ट्रक्टर का उपयोग करने के समान परिणाम नहीं देता है। परिणाम प्राप्त करने के लिए, static
valueOf(double)
विधि का उपयोग करें।
// 0.899999999999999911182158029987476766109466552734375
System.out.println(new BigDecimal((double) (2.00 - 1.10)));
// 0.89999997615814208984375
System.out.println(new BigDecimal((float) (2.00 - 1.10)));
आप देख सकते हैं कि न तो परिणाम वास्तव में है 0.9
। यह केवल एक संयोग है कि Float.toString
उस मामले में 0.9
का उत्पादन होता है और Double.toString
नहीं करता है।
एक साइड नोट के रूप में, (double) (2.00 - 1.10)
एक अनावश्यक कलाकार है। 2.00
और 1.10
पहले से ही double
अक्षर हैं इसलिए अभिव्यक्ति का मूल्यांकन करने का नतीजा पहले से ही double
है। इसके अलावा, float
को घटाने के लिए, आपको (float) 2.00 - (float) 1.10
जैसे दोनों ऑपरेटरों को डालने की आवश्यकता है या साहित्य जैसे 2.00f - 1.10f
का उपयोग करना होगा। (float) (2.00 - 1.10)
केवल float
पर परिणाम डालता है।
पढ़ा [यह] (https://stackoverflow.com/questions/588004/is-floating-point-math-broken) –
"शायद डिफ़ॉल्ट रूप से जावा दोहरी में गणना करता है", '2.00' और' डिफ़ॉल्ट रूप से 1.10' को युगल माना जाता है (जब तक कि आप स्पष्ट रूप से बताते हैं कि उन्हें 'एफ' प्रत्यय जोड़कर फ्लोट किया जाना चाहिए) तो 'डबल + डबल = डबल' का परिणाम जो बताता है कि कास्टिंग '(डबल) (2.00-1.10) ' कुछ भी नहीं बदलता है। – Pshemo
@biziclop, हालांकि कथित डुप्लिकेट इस प्रश्न से संबंधित है; इस मुद्दे के इस संस्करण में भिन्नता है। तथाकथित डुप्लिकेट इस प्रश्न के सबसे मौलिक पहलू को समझाएगा: क्यों डाउनकास्टिंग समस्या को हल करता है? –