2009-02-19 13 views
15

पर डबल परिशुद्धता समस्याओं मैं एक साधारण सी # समारोह है:नेट

public static double Floor(double value, double step) 
{ 
    return Math.Floor(value/step) * step; 
} 

अधिक संख्या में, की तुलना में या "मूल्य" के बराबर है, कि "कदम" के कई है कम की गणना करता है। लेकिन यह परिशुद्धता का अभाव है, निम्नलिखित परीक्षण के रूप में देखा:

[TestMethod()] 
public void FloorTest() 
{ 
    int decimals = 6; 
    double value = 5F; 
    double step = 2F; 
    double expected = 4F; 
    double actual = Class.Floor(value, step); 
    Assert.AreEqual(expected, actual); 
    value = -11.5F; 
    step = 1.1F; 
    expected = -12.1F; 
    actual = Class.Floor(value, step); 
    Assert.AreEqual(Math.Round(expected, decimals),Math.Round(actual, decimals)); 
    Assert.AreEqual(expected, actual); 
} 

पहले और दूसरे का दावा ठीक हैं, लेकिन तीसरे, विफल रहता है क्योंकि परिणाम 6 दशमलव स्थान तक ही बराबर है। ऐसा क्यों है? क्या इसे सही करने का कोई तरीका है?

अद्यतन मैं परीक्षण मुझे लगता है कि मानों 8 दशमलव के बजाय जगह 6 तक बराबर हैं डिबग हैं, तो हो सकता है क्योंकि गणित.गोल कुछ अस्पष्टता परिचय देता है।

नोट मेरे टेस्ट कोड में मैंने "एफ" प्रत्यय (स्पष्ट फ्लोट स्थिर) लिखा जहां मेरा मतलब "डी" (डबल) था, इसलिए यदि मैं इसे बदलता हूं तो मुझे अधिक सटीकता हो सकती है।

उत्तर

5

यदि आप सभी एफ पोस्टफिक्सेस (यानी -12.1-12.1F के बजाय) को छोड़ देते हैं तो आपको कुछ अंकों के बराबर मिल जाएगा। आपके स्थिरांक (और विशेष रूप से अपेक्षित मान) अब F की वजह से फ़्लोट हैं। यदि आप उद्देश्य पर ऐसा कर रहे हैं तो कृपया समझाएं।

लेकिन बाकी के लिए मैं समानता के लिए डबल या फ्लोट मानों की तुलना करने के अन्य उत्तरों के साथ सहमत हूं, यह सिर्फ विश्वसनीय नहीं है।

+0

लेकिन अपरकेस एफ का अर्थ है डबल, फ्लोट नहीं, है ना? लोअरकेस एफ है जिसका मतलब फ्लोट है। –

+0

नहीं, मैंने अभी जांच की है: फ्लोट एक्स = 1.0; एक त्रुटि देता है, फ्लोट एक्स = 1.0 एफ; ठीक है। एफ केस-संवेदी नहीं है। –

+1

और इसे Ecmea334 में देखा: डबल के लिए 1.0 डी, दशमलव के लिए 1.0 एम। –

8

कंप्यूटर पर बिंदु अंकगणित फ्लोटिंग विज्ञान सटीक नहीं हैं :) "की ... सहिष्णुता के भीतर"।

यदि आप पूर्वनिर्धारित दशमलव की सटीक सटीकता चाहते हैं तो दशमलव के बजाय दशमलव का उपयोग करें या मामूली अंतराल को स्वीकार करें।

+5

यह महत्वपूर्ण अंकों की आईईईई परिभाषित संख्या के भीतर एक सटीक विज्ञान है। –

+1

उपरोक्त को मजबूत करने के लिए: फ़्लोटिंग पॉइंट नंबर _are_ सटीक। जो नंबर आप चाहते हैं वह आईईईई फ्लोटिंग पॉइंट नंबर के रूप में प्रदर्शित नहीं हो सकता है, जिसका अर्थ है कि आपको अगले निकटतम नंबर की संख्या को उपनाम करना होगा, जिससे त्रुटि हो जाती है, लेकिन इसका मतलब यह नहीं है कि आपके द्वारा प्रतिनिधित्व की जाने वाली संख्याओं में त्रुटि है उन्हें। – codekaizen

+2

इसके अलावा, डेसिमल डबल्स के समान समस्या से पीड़ित हो सकते हैं, क्योंकि वे भी फ्लोटिंग पॉइंट हैं। वे एक ही प्रतिनिधित्व समस्या का सामना कर सकते हैं, लेकिन यह बहुत कम अप्रत्याशित है, क्योंकि उनके पास 10 का आधार है, बनाम 2 का आधार है, और हम आधार 10 में प्रतिनिधित्व मुद्दों से निपटने के लिए उपयोग किए जाते हैं (उदाहरण के लिए 1/3 0.333333 है .. आधार 10 में)। – codekaizen

1

फ्लोट्स और युगल सभी संख्याओं को सटीक रूप से स्टोर नहीं कर सकते हैं। यह आईईईई फ्लोटिंग पॉइंट सिस्टम के साथ एक सीमा है। वफादार परिशुद्धता रखने के लिए आपको एक और उन्नत गणित पुस्तकालय का उपयोग करने की आवश्यकता है।

यदि आपको किसी निश्चित बिंदु से सटीकता की आवश्यकता नहीं है, तो शायद दशमलव आपके लिए बेहतर काम करेगा। यह डबल की तुलना में एक उच्च परिशुद्धता है।

4

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

उदाहरण के लिए, 0.1 और 0.01 (बाइनरी में) के गैर representability मतलब यह है कि वर्ग 0.1 करने के प्रयास के परिणाम न 0.01 और न ही प्रदर्शनीय संख्या यह के सबसे करीब है।

यदि आप मशीन सिस्टम की मशीन की व्याख्या (बाइनरी) चाहते हैं तो केवल फ़्लोटिंग पॉइंट का उपयोग करें। आप 10 सेंट का प्रतिनिधित्व नहीं कर सकते हैं।

4

यदि आप परिशुद्धता चाहते हैं, तो सिस्टम का उपयोग करें। डेसिमल। यदि आप गति चाहते हैं, तो सिस्टम का उपयोग करें। डबल (या सिस्टम.फ्लैट)। फ़्लोटिंग पॉइंट नंबर "अनंत सटीक" संख्या नहीं हैं, और इसलिए समानता पर जोर देना एक सहिष्णुता शामिल होना चाहिए। जब तक आपकी संख्याओं में महत्वपूर्ण अंकों की उचित संख्या हो, तब तक यह ठीक है।

  • यदि आप बहुत बड़ी और बहुत छोटी संख्याओं पर गणित करना चाहते हैं, तो फ्लोट या डबल का उपयोग न करें।
  • यदि आपको अनंत परिशुद्धता की आवश्यकता है, तो फ्लोट या डबल का उपयोग न करें।
  • यदि आप बहुत अधिक मूल्यों को एकत्रित कर रहे हैं, तो फ्लोट या डबल का उपयोग न करें (त्रुटियां स्वयं को जोड़ती हैं)।
  • यदि आपको गति और आकार की आवश्यकता है, तो फ्लोट या डबल का उपयोग करें।

कैसे सटीक अपने गणितीय क्रियाओं के परिणाम को प्रभावित करता है की एक विस्तृत विश्लेषण के लिए this जवाब (यह भी मेरे द्वारा) देखें।

+0

कोई 'अनंत सटीक' नहीं है। फ्लोट/डबल के साथ समस्या यह है कि वे कई बाइनरी अंकों के लिए सटीक हैं, न कि कई दशमलव अंकों के लिए। – configurator

+2

अनंत परिशुद्धता जैसी चीज है।एक पूर्णांक एक असीमित सटीक प्रकार है। यह गणितीय परिचालन के दौरान कोई परिशुद्धता खो देता है। असीमित सटीक (हालांकि बहुत अक्षम) दशमलव प्रकार को कार्यान्वित करना संभव है, लेकिन यह .Net में "बॉक्स से बाहर" नहीं है। –

+0

माइकल, आपकी टिप्पणी मूर्खतापूर्ण है। इस तरह से परिभाषित किया गया है, ताकि पूर्णांक को "अनंत सटीक" कहा जा सके, क्योंकि वे गणित के संचालन के दौरान परिवर्तन नहीं करते हैं, फिर प्रत्येक संख्या में "अनंत प्रेसिजन" होता है, (फ्लोट, युगल और दशमलव गणित के दौरान बदल नहीं जाते हैं) । इस तरह से परिभाषित, अवधारणा सभी अर्थ खो देता है। बिल्ली, यहां तक ​​कि केवल दो मानों के साथ एक संकेत, (सकारात्मक, या नकारात्मक) में "अनंत प्रेसिजन" है, क्योंकि, आपकी परिभाषा के अनुसार, यह किसी भी गणितीय ऑपरेशन के दौरान कोई परिशुद्धता नहीं खोता है। –

0

समान समस्या के लिए, मैं निम्नलिखित कार्यान्वयन जो अपने परीक्षण मामले के सबसे (5 अंकों परिशुद्धता के लिए) की सफलता के लिए लगता है का उपयोग करते हुए अंत:

public static double roundValue(double rawValue, double valueTick) 
{ 
    if (valueTick <= 0.0) return 0.0; 

    Decimal val = new Decimal(rawValue); 
    Decimal step = new Decimal(valueTick); 
    Decimal modulo = Decimal.Round(Decimal.Divide(val,step)); 

    return Decimal.ToDouble(Decimal.Multiply(modulo, step)); 
} 
8

मैं वास्तव में चाहते हैं एक तरह से उन्हें लागू नहीं किया था फ्लोट्स और युगल के लिए == ऑपरेटर। यह पूछने के लिए लगभग हमेशा गलत बात है कि क्या डबल या फ्लोट किसी अन्य मूल्य के बराबर है या नहीं।

+1

हाँ! हाँ! हाँ! मैं कह रहा हूं कि थोड़ी देर के लिए। यह पूरे 0.999 की तरह है ... = 1.0 समस्या। (1.0 - 0.000 ... = 1.0)। फ़्लोटिंग अंक पूर्णांक की तुलना में एक अलग जानवर हैं। – Josh

0

कभी-कभी परिणाम सख्त से अपेक्षा की तुलना में अधिक सटीक होता है: एफपी आईईईई 754. ऐसा इसलिए है क्योंकि एचडब्ल्यू गणना के लिए अधिक बिट्स का उपयोग करता है। C# specification और this article

जावा में सख्त एफपी कीवर्ड है और सी ++ में कंपाइलर स्विच हैं। मुझे उस विकल्प को याद है .NET