डबल मूल्यों के लिए मुखर तर्क के एप्सिलॉन का अर्थ


187

मेरे पास assertEqualsदोहरे मूल्यों का परीक्षण करने के लिए कनिष्ठ के बारे में एक प्रश्न है । एपीआई डॉक्टर पढ़ना मैं देख सकता हूं:

@Deprecated
public static void assertEquals(double expected, double actual)

पदावनत। इसके बजाय मुखर (डबल उम्मीद, डबल वास्तविक, डबल एप्सिलॉन) का उपयोग करें

epsilonमूल्य का क्या अर्थ है? (एप्सिलॉन ग्रीक वर्णमाला में एक पत्र है, ठीक है?)।

क्या कोई मुझे समझा सकता है कि इसका उपयोग कैसे करें?

जवाबों:


198

एप्सिलॉन वह मान है जो 2 संख्याओं से हो सकता है। तो जब तक यह सच है के लिए मुखर होगाMath.abs(expected - actual) < epsilon


3
तो एप्सिलॉन के रूप में मुझे क्या मूल्य पास करना चाहिए?
पन्नाधाय

15
@ एमराल्ड 214 परिशुद्धता की मात्रा। यदि आप यह दावा करना चाहते हैं कि एक डबल मान 0D एप्सिलॉन होगा 0 (100% सटीकता, कोई अपवाद नहीं)। यदि आप त्रुटि का एक अंश चाहते हैं (डिग्री के लिए कहें) तो आप एप्सिलॉन को 1 अर्थ पर सेट कर सकते हैं, उदाहरण के लिए, 64.2 ° 64.8 ° (अनुपस्थित (64.8-64.2) <1) के समान है
पीटर डे

3
दस्तावेज़ कहता है, "डेल्टा - अपेक्षित और वास्तविक के बीच अधिकतम डेल्टा, जिसके लिए दोनों संख्याओं को अभी भी समान माना जाता है।" इसलिए मुझे लगता है कि ऐसा <=नहीं होना चाहिए <
एंड्रयू चेयोंग

कोड को देखते हुए, मैं इसे विधि doubleIsDifferent(दोहरे मूल्यों की तुलना करने के लिए) कहता हूं और यह वापस आ जाता है Math.abs(d1 - d2) > delta। इसलिए यदि d1 और d2 के बीच का अंतर डेल्टा से अधिक है, तो इसका मतलब है कि मान अलग-अलग हैं और सही वापस आएंगे। यदि मूल्यों को समान माना जाता है तो यह गलत होगा। उस विधि को जोर से सही ढंग से कहा जाता है और यदि यह सही हो जाता है, तो अभिकर्ता फोन करेगा failNotEqualsऔर परीक्षा का परिणाम असफल हो जाएगा।
एंथोमैक्सकोल

1
@jbert क्या कोई सलाह दे सकता है कि एक सामान्य एप्सिलॉन डबल मूल्य क्या होगा यदि मैं बस बहुत अधिक संख्या में औसत के साथ काम कर रहा था या मानक विचलन कर रहा था?
सिमगिनेर

121

यह कौन सा संस्करण है? मैंने केवल डेल्टा देखा है, एप्सिलॉन नहीं - लेकिन यह एक पक्ष मुद्दा है!

JUnit javadoc से :

डेल्टा - अपेक्षित और वास्तविक के बीच अधिकतम डेल्टा जिसके लिए दोनों संख्याओं को अभी भी बराबर माना जाता है।

यह शायद ओवरकिल है, लेकिन मैं आमतौर पर बहुत कम संख्या का उपयोग करता हूं, जैसे

private static final double DELTA = 1e-15;

@Test
public void testDelta(){
    assertEquals(123.456, 123.456, DELTA);
}

यदि आप हैमरेस्ट अभिकथन का उपयोग कर रहे हैं, तो आप मानक का उपयोग equalTo()दो डबल्स के साथ कर सकते हैं (यह डेल्टा का उपयोग नहीं करता है)। हालाँकि, यदि आप एक डेल्टा चाहते हैं, तो आप बस closeTo()( javadoc देखें ), उदाहरण के लिए उपयोग कर सकते हैं

private static final double DELTA = 1e-15;

@Test
public void testDelta(){
    assertThat(123.456, equalTo(123.456));
    assertThat(123.456, closeTo(123.456, DELTA));
}

FYI करें आगामी JUnit 5 दो ड्यूल के साथ कॉल करने पर डेल्टा को वैकल्पिक बना देगा assertEquals()कार्यान्वयन (आप रुचि रखते हैं तो) है:

private static boolean doublesAreEqual(double value1, double value2) {
    return Double.doubleToLongBits(value1) == Double.doubleToLongBits(value2);
}

57

फ्लोटिंग पॉइंट गणना सटीक नहीं है - प्रतिनिधित्व के कारण अक्सर गोल-गोल त्रुटियां होती हैं, और त्रुटियां होती हैं। (उदाहरण के लिए, बाइनरी फ्लोटिंग पॉइंट में 0.1 का बिल्कुल प्रतिनिधित्व नहीं किया जा सकता है।)

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

"डेल्टा", जैसा कि इसे ज्यूनीट जावदोक्स में कहा जाता है , उन अंतरों की मात्रा का वर्णन करता है जिन्हें आप अभी भी समान माना जा सकता है। इस मूल्य का आकार पूरी तरह से उन मूल्यों पर निर्भर करता है जिनकी आप तुलना कर रहे हैं। डबल्स की तुलना करते समय, मैं आमतौर पर 10 ^ 6 से विभाजित अपेक्षित मूल्य का उपयोग करता हूं।


11

बात यह है कि फ्लोटिंग पॉइंट नंबरों में निहित सटीक मुद्दों के कारण दो डबल बिल्कुल समान नहीं हो सकते हैं। इस डेल्टा मान से आप एक त्रुटि कारक के आधार पर समानता के मूल्यांकन को नियंत्रित कर सकते हैं।

इसके अलावा कुछ फ्लोटिंग-पॉइंट वैल्यू में NAN और -Infinity / + Infinity जैसे विशेष मूल्य हो सकते हैं जो परिणामों को प्रभावित कर सकते हैं।

यदि आप वास्तव में तुलना करने का इरादा रखते हैं कि दो डबल्स बिल्कुल बराबर हैं, तो उन्हें लंबे प्रतिनिधित्व के रूप में तुलना करना सबसे अच्छा है

Assert.assertEquals(Double.doubleToLongBits(expected), Double.doubleToLongBits(result));

या

Assert.assertEquals(0, Double.compareTo(expected, result));

जो इन बारीकियों को ध्यान में रख सकते हैं।

मैंने प्रश्न में मुखर विधि में विलंब नहीं किया है, लेकिन मैं केवल यह मान सकता हूं कि पिछले इस तरह के मुद्दों के लिए पदावनत किया गया था और नया उन्हें ध्यान में रखता है।


2

एप्सिलॉन एक अंतर expectedऔर actualमूल्यों के बीच का अंतर है जिसे आप यह सोचकर स्वीकार कर सकते हैं कि वे समान हैं। आप .1उदाहरण के लिए सेट कर सकते हैं ।


2

ध्यान दें कि यदि आप गणित नहीं कर रहे हैं, तो सटीक फ़्लोटिंग पॉइंट मानों को सम्मिलित करने में कुछ भी गलत नहीं है। उदाहरण के लिए:

public interface Foo {
    double getDefaultValue();
}

public class FooImpl implements Foo {
    public double getDefaultValue() { return Double.MIN_VALUE; }
}

इस मामले में, आप यह सुनिश्चित करना चाहते हैं कि यह वास्तव में है MIN_VALUE, शून्य -MIN_VALUEया MIN_NORMALया कुछ अन्य बहुत छोटा मूल्य नहीं है। तुम कह सकते हो

double defaultValue = new FooImpl().getDefaultValue();
assertEquals(Double.MIN_VALUE, defaultValue);

लेकिन इससे आपको डेप्रिसिएशन की चेतावनी मिलेगी। इससे बचने के लिए, आप assertEquals(Object, Object)इसके बजाय कॉल कर सकते हैं :

// really you just need one cast because of autoboxing, but let's be clear
assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);

और, यदि आप वास्तव में चतुर दिखना चाहते हैं:

assertEquals(
    Double.doubleToLongBits(Double.MIN_VALUE), 
    Double.doubleToLongBits(defaultValue)
);

या आप बस Hamcrest धाराप्रवाह शैली का उपयोग कर सकते हैं:

// equivalent to assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);
assertThat(defaultValue, is(Double.MIN_VALUE));

मूल्य आप कर रहे हैं की जाँच तो है कुछ गणित कर रही है से आते हैं, हालांकि, एप्सिलॉन का उपयोग करें।


7
यदि आप वास्तव में बराबर की जाँच करना चाहते हैं, तो एप्सिलॉन को 0.0 पर सेट करें - ऑब्जेक्ट वेरिएंट की आवश्यकता नहीं है।
मेल निकोलसन

-2
Assert.assertTrue(Math.abs(actual-expected) == 0)

फ्लोटिंग पॉइंट नंबरों (जैसे फ्लोट या डबल) का उपयोग करते समय, यह मज़बूती से काम नहीं करने वाला है। आप समीक्षा करना चाहते हैं कि जावा में फ्लोटिंग पॉइंट नंबर कैसे संग्रहीत किए जाते हैं और उन पर अंकगणितीय संचालन कैसे काम करते हैं। (बिगाड़ने: कुछ गोल त्रुटियों की उम्मीद!)
एटिला
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.