2011-09-17 23 views
26

मेरे पास एक डबल "138630.78380386264" है और मैं इसे दशमलव में परिवर्तित करना चाहता हूं, हालांकि जब मैं ऐसा करता हूं तो मैं इसे या तो कास्टिंग करके या Convert.ToDecimal() का उपयोग करके करता हूं और मैं सटीकता खो देता हूं।सी # दशमलव से सटीक हानि

क्या चल रहा है? दोनों दशमलव और डबल के लिए इस नंबर का आयोजन कर सकते हैं:

enter image description here

double doub = double.Parse("138630.78380386264"); 
decimal dec = decimal.Parse("138630.78380386264"); 
string decs = dec.ToString("F17"); 
string doubse =DoubleConverter.ToExactString(doub); 
string doubs = doub.ToString("F17"); 

decimal decC = (decimal) doub; 
string doudeccs = decC.ToString("F17"); 
decimal decConv = Convert.ToDecimal(doub); 
string doudecs = decConv.ToString("F17"); 

इसके अलावा: मैं डबल पर ToString() कैसे प्राप्त कर सकते हैं बाहर डिबगर शो के रूप में एक ही परिणाम मुद्रित करने के लिए? जैसे 138630.78380386264?

+0

संभावित डुप्लिकेट [एक अंतर में सी # परिणामों में दशमलव से दो अंकों का रूपांतरण] (http://stackoverflow.com/questions/1584314/conversion-of-a-decimal-to-double-number-in- सी-परिणाम-में-एक अंतर) –

+1

अच्छी तरह से कनवर्ट करें। टोडडिमल (somedouble) बराबर (दशमलव) के बराबर बराबर है, इसलिए कोई आश्चर्य नहीं है। मुझे यकीन नहीं है कि क्यों उस कलाकार ने अंतिम अंक को गोल किया है। – harold

+0

@harold आप धोखा दिया गया था। यह निकटतम के लिए दौर करता है। डबल मान 386264 समाप्त होता है और 15 सिग अंजीर दशमलव 3863 समाप्त होता है। –

उत्तर

23

138630.78380386264 डबल परिशुद्धता के लिए बिल्कुल प्रतिनिधित्व नहीं किया जा सकता है। निकटतम डबल परिशुद्धता संख्या (जैसा कि here मिला) 138630.783803862635977566242218017578125 है, जो आपके निष्कर्षों से सहमत है।

आप पूछते हैं कि दशमलव में रूपांतरण में अधिक सटीकता क्यों नहीं है। documentation for Convert.ToDecimal() का उत्तर है:

इस विधि द्वारा लौटाए गए दशमलव मूल्य में अधिकतम 15 महत्वपूर्ण अंक हैं। यदि मान पैरामीटर में 15 से अधिक महत्वपूर्ण अंक हैं, तो यह निकटतम के लिए गोल करने का उपयोग करके गोल किया जाता है। निम्न उदाहरण दिखाता है कि कनवर्ट। टूडेसिमल (डबल) विधि 15 महत्वपूर्ण अंकों के साथ दशमलव दशमलव को वापस करने के लिए निकटतम के लिए गोल करने का उपयोग करती है।

15 महत्वपूर्ण आंकड़ों पर निकटतम के लिए गोलाकार डबल मान 138630.783803863 है, जैसा कि आप ऊपर दिखाते हैं।

+0

तो दशमलव में रूपांतरण अधिक सटीकता क्यों नहीं उठाता है? – GreyCloud

+0

ठीक है कि इसे समझाने के लिए धन्यवाद। क्या टॉस्ट्रिंग को 15 से अधिक सिग अंजीर प्रिंट करने के लिए वैसे भी है? - मैं मूल स्ट्रिंग पर वापस जाने में सक्षम होना चाहता हूं - इस तरह मैं स्ट्रिंग को पार्स करने के लिए डबल प्राप्त कर सकता हूं और सटीकता को खोए बिना रूपांतरण कर सकता हूं – GreyCloud

+0

'doub.ToString (" G17 ") 'आपको वही स्ट्रिंग देगा कि डीबगर उत्पादन करता है। लेकिन मुझे यकीन नहीं है कि डीबगर क्या कर रहा है। चूंकि 'डबल' सीमित परिशुद्धता है, इसलिए आप सामान्य रूप से स्ट्रिंग को पार्स करने में सक्षम नहीं होंगे और फिर मूल स्ट्रिंग वापस प्राप्त करेंगे। यदि आपको मूल स्ट्रिंग को जानने की आवश्यकता है, तो याद रखें। –

4

यह एक दुर्भाग्यपूर्ण है, मुझे लगता है। 13 9, 000 के करीब, DecimalDouble से कहीं बेहतर परिशुद्धता है। लेकिन फिर भी, इस मुद्दे के कारण, हमारे पास अलगDouble का अनुमान परDecimal पर प्रक्षेपित किया जा रहा है। उदाहरण

double doub1 = 138630.7838038626; 
double doub2 = 138630.7838038628; 
Console.WriteLine(doub1 < doub2);     // true, values differ as doubles 
Console.WriteLine((decimal)doub1 < (decimal)doub2); // false, values projected onto same decimal 

वास्तव में के लिए वहाँ छह विभिन्न प्रदर्शनीय Double मूल्यों के बीच doub1 और ऊपर doub2 हैं, इसलिए वे ही नहीं हैं।

static decimal PreciseConvert(double doub) 
{ 
    // Handle infinities and NaN-s first (throw exception) 
    // Otherwise: 
    return Decimal.Parse(doub.ToString("R"), NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint); 
} 

"R" प्रारूप स्ट्रिंग सुनिश्चित करता है कि पर्याप्त अतिरिक्त आंकड़े मानचित्रण injective बनाने के लिए (डोमेन जहां Decimal बेहतर परिशुद्धता है में) शामिल किए गए हैं:

यहाँ कुछ हद तक एक मूर्खतापूर्ण काम aronud है।


ध्यान दें कि कुछ सीमा में, एक long (Int64) एक सटीक है कि Double की है कि बेहतर है। इसलिए मैंने जांच की कि यहां रूपांतरण समान तरीके से किए गए हैं (पहले 15 महत्वपूर्ण दशमलव स्थानों पर गोल)। वो नहीं हैं! तो:

double doub3 = 1.386307838038626e18; 
double doub4 = 1.386307838038628e18; 

Console.WriteLine(doub3 < doub4);    // true, values differ as doubles 
Console.WriteLine((long)doub3 < (long)doub4); // true, full precision of double used when converting to long 

यह एक अलग "नियम" का उपयोग करने के लिए जब लक्ष्य decimal है असंगत लगता है।

ध्यान दें कि इस वजह से, (decimal)(long)doub3 केवल (decimal)doub3 से अधिक सटीक परिणाम उत्पन्न करता है।

+0

समस्या 13 9, 000 के करीब संख्याओं के साथ नहीं है क्योंकि डबल की सटीकता 16 अंकों की है, इससे कोई फर्क नहीं पड़ता कि क्या विभाजक के बाएं या दाहिने तरफ अंक हैं, यदि आप इस नंबर को कम करते हैं 13.86307838038626 पर आपको एक ही समस्या होगी। दशमलव में 32 अंकों की सटीकता है, यही कारण है कि आपको यह समस्या नहीं है। –

+0

@ गेब्रियलवोनलांटन सी। लोपस आप इस समस्या का सही हैं 13 9, 000 के पास संख्याओं के लिए विशिष्ट नहीं है। मैंने केवल उस संख्या को एक उदाहरण के रूप में माना, चुना गया क्योंकि यह मूल प्रश्न में संख्या थी। वास्तव में (बहुत मोटे तौर पर) '1e-12' और' 1e + 2 9 'के बीच की सभी संख्याएं एक ही समस्या है। इस सीमा के बाहर एक 'दशमलव' या तो परिभाषित नहीं किया गया है, या अब 'डबल' से अधिक सटीकता नहीं है। (हालांकि, 'दशमलव' में 28-29 अंक की सटीकता है।) –

संबंधित मुद्दे