2010-03-09 13 views
45

http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspxDouble.Epsilon, से अधिक है, कम से कम, कम से कम या इसके बराबर

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

तो यह वास्तव में एक एप्सिलॉन कि तुलना के लिए इस्तेमाल किया जा सकता है? मैं वास्तव में एमएसडीएन शब्दकोष को समझ नहीं पा रहा हूं।

क्या इसे यहां उदाहरणों में ईपीएसलॉन के रूप में उपयोग किया जा सकता है? - What is the most effective way for float and double comparison?

और अंततः यह वास्तव में महत्वपूर्ण लगता है इसलिए मैं यह सुनिश्चित करना चाहता हूं कि मेरे पास समानता के लिए ठोस कार्यान्वयन है, उससे कम, उससे कम, उससे कम या बराबर, और इससे अधिक या बराबर।

उत्तर

66

मुझे नहीं पता वे लिखते समय धूम्रपान कर रहे थे। Double.Epsilon सबसे छोटा प्रतिनिधित्व करने वाला गैर-डिमॉर्मल फ़्लोटिंग पॉइंट मान है जो 0 नहीं है। आप सभी जानते हैं कि यदि कोई छंटनी त्रुटि है, तो यह हमेशा इस मान से बड़ा होगा। और अधिक बड़ा।

System.Double प्रकार 15 अंकों तक सटीक मानों का प्रतिनिधित्व कर सकता है। तो एक सरल पहले के आदेश का अनुमान है, तो एक डबल मूल्य x कुछ निरंतर के बराबर होता है निरंतर * का एक एप्सिलॉन का उपयोग करने के 1E-15

public static bool AboutEqual(double x, double y) { 
    double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15; 
    return Math.Abs(x - y) <= epsilon; 
} 

आप हालांकि बाहर देखने के लिए, काट-छांट त्रुटियों जमा कर सकते हैं। यदि x और y दोनों गणना मूल्य हैं तो आपको ईपीएसलॉन को बढ़ाना होगा।

+8

माइक्रोसॉफ्ट का कहना है 'प्रतिनिधित्व करता है शून्य से अधिक छोटा सबसे छोटा सकारात्मक मान। 'http://msdn.microsoft.com/en-us/library/system.double.epsilon%28v=vs.110%29.aspx देखें। –

+1

@ इयान यही है 'डबल.इप्सिलॉन' होना चाहिए, लेकिन david.pfx इसे परिभाषित करता है क्योंकि यह है :-( –

+0

1.0 + डबल.इप्सिलॉन = 1.0 –

4

इसका उपयोग तुलना के लिए किया जा सकता है, यह मानते हुए कि आप यह सुनिश्चित करना चाहते हैं कि दो मान या तो बराबर बराबर हों, या डबल प्रकार के लिए सबसे छोटा प्रतिनिधित्व करने वाला अंतर हो। आम तौर पर, आप double.Epsilon से अधिक संख्या का उपयोग करना चाहते हैं यह जांचने के लिए कि दो युगल लगभग बराबर हैं या नहीं।

क्यों .NET फ़्रेमवर्क

bool IsApproximatelyEqual(double value, double permittedVariance); 

की तरह कुछ को परिभाषित नहीं करता मुझे परे है।

3

मुझे लगता है कि MSDN लिंक आप पोस्ट में प्रासंगिक बिट्स ये हैं:

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

नोट: एप्सिलॉन संपत्ति के मूल्य मशीन एप्सिलॉन, जो फ्लोटिंग प्वाइंट गणित में गोलाई ऊपरी की वजह से रिश्तेदार त्रुटि के लिए बाध्य का प्रतिनिधित्व करता है के बराबर नहीं है।

यह मान के रूप में छोटी से छोटी धनात्मक संख्या एक्स परिभाषित नहीं है, ऐसी है कि एक्स + 1.0 , 1.0 के बराबर नहीं है तो Double.Epsilon "लगभग समानता" के लिए इस्तेमाल नहीं किया जा सकता। ढांचे में कोई स्थिरता नहीं है जिसका मान सबसे छोटा सकारात्मक संख्या x है, जैसे कि x + 1.0 1.0 के बराबर नहीं है।

मुझे कहना है, मुझे आश्चर्य है। मैंने भी यह माना था कि डबल। एपिसिल सी/सी ++ में डीबीएल_ईपीएसिलॉन के बराबर था - स्पष्ट रूप से नहीं!

जो मैं उस लिंक के बारे में पढ़ सकता हूं उससे ऐसा लगता है कि 'आपको तुलना के लिए एक सभ्य मूल्य को समझने की आवश्यकता है' जो कम से कम कहने के लिए आश्चर्यजनक है।
संभवतः किसी ने अधिक जानकार स्पष्ट कर सकते हैं :)

9

आप दो डबल मानों 1.0 के करीब हैं, लेकिन वे केवल अपने कम से कम महत्वपूर्ण बिट में भिन्न होते हैं, तो उनके बीच के अंतर परिमाण के कई क्रमों डबल से अधिक हो जाएगा .Epsilon। वास्तव में, अंतर परिमाण के 324 दशमलव आदेश है। यह एक्सपोनेंट हिस्से के प्रभाव के कारण है। डबल.इप्सिलॉन पर इसका एक बड़ा नकारात्मक एक्सपोनेंट है, जबकि 1.0 में शून्य का एक्सपोनेंट है (पूर्वाग्रह को हटाए जाने के बाद)।

यदि आप समानता के लिए दो समान मानों की तुलना करना चाहते हैं, तो आपको एक कस्टम ईपीएसलॉन मान चुनना होगा जो मूल्यों के ऑर्डर-आयाम आकार के लिए उपयुक्त है।

यदि आप जिन डबल मानों की तुलना कर रहे हैं वे 1.0 के करीब हैं। फिर कम से कम सिग्निफिशेंट बिट का मूल्य 0.0000000000000001 के पास होगा। यदि आप तुलना कर रहे डबल मान क्वाड्रिलियंस में हैं, तो कम से कम महत्वपूर्ण बिट का मान हजारों तक हो सकता है। उन दोनों परिस्थितियों में समानता तुलना के लिए ईपीएसलॉन के लिए कोई भी एकल उपयोग नहीं किया जा सकता था।

1

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

39

मैं यह सुनिश्चित करना चाहता हूं कि मेरे पास समानता के लिए ठोस कार्यान्वयन है, उससे कम, उससे कम, उससे कम या बराबर, और इससे अधिक या बराबर।

आप बाइनरी फ़्लोटिंग पॉइंट अंकगणित का उपयोग कर रहे हैं।

बाइनरी फ्लोटिंग पॉइंट अंकगणित को भौतिक मात्रा जैसे लंबाई, द्रव्यमान, चार्ज, समय आदि का प्रतिनिधित्व करने के लिए डिज़ाइन किया गया था।

संभवतः आप बाइनरी फ्लोटिंग पॉइंट अंकगणित का उपयोग कर रहे हैं क्योंकि इसका उपयोग किया जाना था: भौतिक मात्रा पर अंकगणित करने के लिए।

भौतिक मात्राओं के माप हमेशा मापने के लिए उपयोग किए जाने वाले डिवाइस की परिशुद्धता के आधार पर एक विशेष परिशुद्धता रखते हैं।

चूंकि आप उन मात्राओं के मूल्य प्रदान करते हैं जो आप जोड़ रहे हैं, आप ही जानते हैं कि उस मात्रा पर "त्रुटि बार" क्या हैं। उदाहरण के लिए, यदि आप मात्रा प्रदान कर रहे हैं "इमारत की ऊंचाई 123.56 मीटर है" तो आप जानते हैं कि यह सेंटीमीटर के लिए सटीक है, लेकिन माइक्रोमीटर के लिए नहीं।

इसलिए, समानता के लिए दो मात्रा की तुलना करते समय, वांछित अर्थशास्त्र यह कहना है कि "क्या ये माप दो मापों द्वारा निर्दिष्ट त्रुटि बार के बराबर हैं?"

तो अब हमारे पास आपके प्रश्न का उत्तर है। आपको क्या करना चाहिए यह ट्रैक रखें कि प्रत्येक मात्रा में त्रुटि क्या है; उदाहरण के लिए, इमारत की ऊंचाई "123.56 मीटर के 0.01 के भीतर" है क्योंकि आप जानते हैं कि यह माप कितना सटीक है। यदि आप एक और माप प्राप्त करते हैं जो 123.5587 है और यह जानना चाहते हैं कि दो माप त्रुटि सहनशीलता के भीतर "बराबर" हैं, तो घटाएं और देखें कि यह त्रुटि सहनशीलता में पड़ता है या नहीं। इस मामले में यह करता है। यदि माप वास्तव में माइक्रोमैरेरे के लिए सटीक थे, तो वे बराबर नहीं हैं।

संक्षेप में: आप यहां अकेले व्यक्ति हैं जो जानते हैं कि समझदार त्रुटि सहनशीलता क्या है, क्योंकि आप अकेले व्यक्ति हैं जो जानते हैं कि आप जिन आंकड़ों को जोड़ रहे हैं, वे पहले स्थान पर आए थे। आपके द्वारा उपयोग किए जाने वाले उपकरणों की सटीकता को देखते हुए आपके माप के लिए जो भी त्रुटि सहनशीलता समझ में आता है उसका उपयोग करें।

+2

निश्चित रूप से यह इंगित करने के लिए सही है कि सहिष्णुता परिभाषित करने के लिए एक अधिक व्यावहारिक और सीधा उपाय है, मैं एक सामान्य प्रथम पास नियम के रूप में एन्कोडेड प्रतिनिधित्व की त्रुटियों को देख रहा था और सहिष्णुता विशिष्ट स्थिति के आधार पर वैकल्पिक वैकल्पिक पास होगी। – ss2k

+1

एरिक, यदि आप डेटा संरचना (जैसे खेल के लिए) का कुछ हिस्सा बनाते हैं और अन्य गेमों को इसका उपयोग करने की अनुमति देना चाहते हैं, तो सभी को अलग-अलग सहनशीलता प्रणाली का उपयोग करने के लिए अलग-अलग सहनशीलता होगी। तो, यह तय करना कि आपका ईपीएसलॉन क्या होगा, केवल व्यक्तिगत परिस्थितियों का मामला नहीं है, मुझे लगता है। – Tom

+2

आपने इस प्रश्न का उत्तर नहीं दिया। यह स्वाद या संदर्भ का सवाल नहीं है, यह स्मृति में एक डबल (आईईईई 754) की परिभाषा से संबंधित है। –

0

यहाँ कुछ कोड है कि Silverlight नियंत्रण टूलकिट के भीतर दो बार शामिल है:

public static bool AreClose(double value1, double value2) 
    { 
     //in case they are Infinities (then epsilon check does not work) 
     if(value1 == value2) return true; 
     // This computes (|value1-value2|/(|value1| + |value2| + 10.0)) < DBL_EPSILON 
     double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DBL_EPSILON; 
     double delta = value1 - value2; 
     return(-eps < delta) && (eps > delta); 
    } 

एक ही स्थान पर वे एप्सिलॉन के लिए 1e-6 का उपयोग करें; दूसरे में वे 1.192093E-07 का उपयोग करते हैं। आप अपना खुद का ईपीएसलॉन चुनना चाहेंगे।

+0

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

5

मैंने अभी यह किया - केंट बोगर्ट्स विचार का उपयोग करके।

private bool IsApproximatelyEqual(double x, double y, double acceptableVariance) 
{ 
    double variance = x > y ? x - y : y - x; 
    return variance < acceptableVariance; 

    //or 
    //return Math.Abs(x - y) < acceptableVariance; 
} 
0

कोई विकल्प नहीं है कि आपको इसे स्वयं की गणना करनी है या अपने निरंतर परिभाषित करना है।

double calculateMachineEpsilon() { 
    double result = 1.0; 
    double one = 1.0/256; 

    while(one + result/2.0 != 1.0) { 
     result/=2.0; 
    } 
    return result; 
} 
0

मैं उपयोग

public static class MathUtil { 
    /// <summary> 
    /// smallest such that 1.0+EpsilonF != 1.0 
    /// </summary> 
    public const float EpsilonF = 1.192092896e-07F; 

    /// <summary> 
    /// smallest such that 1.0+EpsilonD != 1.0 
    /// </summary> 
    public const double EpsilonD = 2.2204460492503131e-016; 

    [MethodImpl(MethodImplOptions.AggressiveInlining)] 
    public static bool IsZero(this double value) { 
     return value < EpsilonD && value > -EpsilonD; 
    } 

    [MethodImpl(MethodImplOptions.AggressiveInlining)] 
    public static int Sign(this double value) { 
     if (value < -EpsilonD) { 
      return -1; 
     } 
     if (value > EpsilonD) 
      return 1; 
     return 0; 
    } 

निम्नलिखित और आप दो डबल्स 'एक' और 'बी' की समानता के लिए जाँच करना चाहते हैं, तो आप

(a-b).IsZero(); 

और यदि आप उपयोग कर सकते हैं तुलना परिणाम प्राप्त करना चाहते हैं,

(a-b).Sign();