2011-04-16 12 views
153

मुझे डबल मानों का परीक्षण करने के लिए जूनिट assertEquals के बारे में एक सवाल है। पढ़ना एपीआई डॉक मैं देख सकता हूँ:डबल मानों के लिए assertEquals के epsilon तर्क का अर्थ

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

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

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

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

उत्तर

168

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

+1

तो मुझे ईपीएसलॉन के रूप में क्या मूल्य पारित करना चाहिए? – Emerald214

+10

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

1

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

52

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

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

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

10

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

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

तुम सच में तुलना करने के लिए है कि दो युगल बिल्कुल बराबर यह सबसे अच्छा है कर रहे हैं चाहते हैं तो एक लंबे समय के प्रतिनिधित्व के रूप में उनकी तुलना

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

या

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

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

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

96

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

JUnit javadoc से:

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

यह शायद अधिक है, लेकिन मैं आमतौर पर वास्तव में एक छोटी संख्या का उपयोग करता हूं, उदाहरण के लिए

private static final double DELTA = 1e-15; 

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

आप hamcrest कथनों का उपयोग कर रहे हैं, तो आप सिर्फ दो युगल (यह एक डेल्टा का उपयोग नहीं करता है) के साथ मानक 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 भी make delta optional जब दो युगल के साथ assertEquals() बुला होगा। implementation (यदि आप रुचि रखते हैं) है:

private static boolean doublesAreEqual(double value1, double value2) { 
    return Double.doubleToLongBits(value1) == Double.doubleToLongBits(value2); 
} 
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)); 

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

+6

यदि आप जांचना चाहते हैं एक बिल्कुल बराबर है, epsilon 0.0 को सेट करें - ऑब्जेक्ट संस्करण की आवश्यकता नहीं है। –

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