2009-02-17 13 views
19

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

def nearlyequal(a, b, sigfig=5): 

इस समारोह का उद्देश्य यह दो फ्लोटिंग प्वाइंट संख्या निर्धारित करने के लिए है (ए और बी) के लगभग बराबर है। फ़ंक्शन वापस लौटाएगा यदि एक == बी (सटीक मिलान) या यदि ए और बी के पास समान मान है तो sigfig दशमलव में लिखे गए महत्वपूर्ण आंकड़े।

क्या कोई भी अच्छा कार्यान्वयन सुझा सकता है? मैंने मिनी यूनिट-टेस्ट लिखा है। जब तक आप मेरे परीक्षण में एक बग देख सकते हैं तो एक अच्छा कार्यान्वयन निम्नलिखित पारित करना चाहिए:

assert nearlyequal(1, 1, 5) 
assert nearlyequal(1.0, 1.0, 5) 
assert nearlyequal(1.0, 1.0, 5) 
assert nearlyequal(-1e-9, 1e-9, 5) 
assert nearlyequal(1e9, 1e9 + 1 , 5) 
assert not nearlyequal(1e4, 1e4 + 1, 5) 
assert nearlyequal(0.0, 1e-15, 5) 
assert not nearlyequal(0.0, 1e-4, 6) 

अतिरिक्त नोट्स:

  1. मान ए और बी प्रकार int, नाव या numpy.float64 का हो सकता है। मान ए और बी हमेशा एक ही प्रकार के होंगे। यह महत्वपूर्ण है कि रूपांतरण फ़ंक्शन में अतिरिक्त त्रुटि नहीं पेश करता है।
  2. आइए इसे संख्यात्मक रखें, इसलिए स्ट्रिंग्स में कनवर्ट करने या गैर-गणितीय चाल का उपयोग करने वाले फ़ंक्शंस आदर्श नहीं हैं। इस कार्यक्रम का लेखा किसी ऐसे व्यक्ति द्वारा किया जाएगा जो गणितज्ञ है जो यह साबित करने में सक्षम होना चाहता है कि समारोह वह करता है जो इसे करना है।
  3. गति ... मुझे बहुत सी संख्याओं की तुलना करना है ताकि तेज़ी से बेहतर हो।
  4. मुझे numpy, scipy और मानक-पुस्तकालय मिला है। मेरे लिए कुछ भी मुश्किल होगा, खासकर परियोजना के इस तरह के एक छोटे से हिस्से के लिए।
+1

[फ़्लोटिंग प्वाइंट नंबर की तुलना, 2012 संस्करण] (https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/) – endolith

उत्तर

18

numpy.testing (स्रोत here) में एक समारोह assert_approx_equal जो एक अच्छा प्रारंभिक बिंदु हो सकता है नहीं है।

def assert_approx_equal(actual,desired,significant=7,err_msg='',verbose=True): 
    """ 
    Raise an assertion if two items are not equal up to significant digits. 

    .. note:: It is recommended to use one of `assert_allclose`, 
       `assert_array_almost_equal_nulp` or `assert_array_max_ulp` 
       instead of this function for more consistent floating point 
       comparisons. 

    Given two numbers, check that they are approximately equal. 
    Approximately equal is defined as the number of significant digits 
    that agree. 
+0

unittest.assertAlmostEqual() ने मुझे अनजान द्वारा बेवकूफ़ बना दिया जी महत्वहीन अंक। – Hauke

7

यहां एक लेना है।

def nearly_equal(a,b,sig_fig=5): 
    return (a==b or 
      int(a*10**sig_fig) == int(b*10**sig_fig) 
      ) 
+0

आपको वास्तव में उस वक्तव्य की आवश्यकता नहीं है । आप तुलनात्मक परिणाम का परिणाम वापस कर सकते हैं: यह या तो सत्य या गलत है, यह छोटा और निश्चित रूप से अधिक पायथनिक – SilentGhost

+0

यह काम _nearlyequal ((1e9,1 + 1e9, 5) _? – nlucaroni

+0

अच्छा बिंदु @ सिलेंघोस्ट के लिए काम करेगा। परिवर्तन किया गया। – Triptych

2

दशमलव में "महत्वपूर्ण आंकड़े" दशमलव बिंदु को समायोजित करने और पूर्णांक को छंटनी करने का विषय है।

>>> int(3.1415926 * 10**3) 
3141 
>>> int(1234567 * 10**-3) 
1234 
>>> 
+0

क्या आप ऐसा करने के लिए एल्गोरिदम प्रदान कर सकते हैं? –

+0

कोड से अलग मैंने पहले ही पोस्ट किया है? आपको और जानने की क्या आवश्यकता है? –

4

मेरा मानना ​​है कि आपके सवाल का काफी अच्छी तरह से परिभाषित नहीं है, और इकाई परीक्षण आप को साबित पेश यह:

यदि 'राउंड टू एन सिग-अंजीर दशमलव स्थानों' से आपका मतलब 'दशमलव बिंदु के दाईं ओर एन दशमलव स्थान' है, तो परीक्षण assert nearlyequal(1e9, 1e9 + 1 , 5) विफल होना चाहिए, क्योंकि जब भी आप 1000000000 और 1000000001 से 0.00001 सटीकता, वे अभी भी अलग हैं।

और यदि 'राउंड टू एन सिग-अंजीर दशमलव स्थानों' से आपका मतलब है 'दशमलव बिंदु के बावजूद एन सबसे महत्वपूर्ण अंक', तो परीक्षण assert nearlyequal(-1e-9, 1e-9, 5) विफल होना चाहिए, क्योंकि 0.000000001 और -0.000000001 देखे जाने पर पूरी तरह अलग हैं इस तरफ।

यदि आप पहली परिभाषा का मतलब रखते हैं, तो इस पृष्ठ पर पहला जवाब (Triptych द्वारा) अच्छा है। यदि आप दूसरी परिभाषा का मतलब रखते हैं, तो कृपया इसे कहें, मैं इसके बारे में सोचने का वादा करता हूं :-)

+0

दरअसल, आप "लगभग असमान (-1e-9, 1e-9, 5)" के बारे में सही हैं - यह नियमों को तोड़ देता है! +1 –

1

यह फ़्लोटिंग पॉइंट नंबरों के साथ एक आम बात है। मैं डेममेल [1] की धारा 1.5 में चर्चा के आधार पर इसे हल करता हूं। (1) राउंडऑफ त्रुटि की गणना करें। (2) जांचें कि राउंडऑफ त्रुटि कुछ ईपीएसलॉन से कम है। मैंने कुछ समय में पायथन का उपयोग नहीं किया है और केवल संस्करण 2.4.3 है, लेकिन मैं इसे सही करने का प्रयास करूंगा।

चरण 1. roundoff त्रुटि

def roundoff_error(exact, approximate): 
    return abs(approximate/exact - 1.0) 

चरण 2. चल बिन्दु समानता

def float_equal(float1, float2, epsilon=2.0e-9): 
    return (roundoff_error(float1, float2) < epsilon) 

इस कोड के साथ एक जोड़े को स्पष्ट कमियों रहे हैं।

  1. सटीक मान शून्य होने पर शून्य त्रुटि से डिवीजन शून्य है।
  2. यह सत्यापित नहीं करता है कि तर्क फ़्लोटिंग पॉइंट मान हैं।

संशोधन 1.

def roundoff_error(exact, approximate): 
    if (exact == 0.0 or approximate == 0.0): 
     return abs(exact + approximate) 
    else: 
     return abs(approximate/exact - 1.0) 

def float_equal(float1, float2, epsilon=2.0e-9): 
    if not isinstance(float1,float): 
     raise TypeError,"First argument is not a float." 
    elif not isinstance(float2,float): 
     raise TypeError,"Second argument is not a float." 
    else: 
     return (roundoff_error(float1, float2) < epsilon) 

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

इस बिंदु पर, एकमात्र मुश्किल बात ईपीएसलॉन के लिए सही मूल्य निर्धारित कर रही है। मैंने संस्करण 2.6.1 के लिए प्रलेखन में देखा कि sys.float_info में एक ईपीएसलॉन विशेषता है, इसलिए मैं डिफ़ॉल्ट ईपीएसलॉन के रूप में उस मूल्य को दो बार उपयोग करूंगा। लेकिन सही मूल्य आपके आवेदन और आपके एल्गोरिदम दोनों पर निर्भर करता है।

[1] जेम्स डब्ल्यू Demmel, एप्लाइड संख्यात्मक रेखीय बीजगणित, सियाम, के रूप में कहा गया है 1997

1

Oren Shemesh समस्या के साथ समस्या का एक हिस्सा मिल गया लेकिन वहाँ और भी है:

ज़ोर nearlyequal (0.0, 1e-15, 5)

भी दूसरी परिभाषा में विफल रहता है (और है कि परिभाषा मैं स्कूल में सीखा है।)

कोई फर्क नहीं पड़ता कि कितने अंक आप पर, 0 बराबर नहीं होगा एक नहीं देख रहे हैं टी शून्य। यदि आपके पास ऐसा कोई मामला है जिसका सही उत्तर शून्य है, तो यह ऐसे परीक्षणों के लिए सिरदर्द साबित हो सकता है।

3

वहां पहले से ही महान जवाब के बहुत सारे हैं, लेकिन यहां एक थिंक है:

def closeness(a, b): 
    """Returns measure of equality (for two floats), in unit 
    of decimal significant figures.""" 
    if a == b: 
    return float("infinity") 
    difference = abs(a - b) 
    avg = (a + b)/2 
    return math.log10(avg/difference) 


if closeness(1000, 1000.1) > 3: 
    print "Joy!" 
1

बी डावसन (सी ++ कोड के साथ) "Comparing Floating Point Numbers" पर द्वारा इस के लिए एक दिलचस्प समाधान नहीं है। उनका दृष्टिकोण दो संख्याओं के सख्त आईईईई प्रतिनिधित्व और लागू किए गए लेक्सिकोोग्राफ़िकल ऑर्डरिंग पर निर्भर करता है जब कहा गया संख्या संख्याबद्ध पूर्णांक के रूप में प्रदर्शित होती है।

0

दो संख्याओं की तुलना करने के कई तरीके हैं यह देखने के लिए कि क्या वे एन महत्वपूर्ण अंकों से सहमत हैं। आप शायद ही यह सुनिश्चित करना चाहते हैं कि उनका अंतर 10^-N बार से कम है, दो संख्याओं में से सबसे बड़ा तुलना की जा रही है। यह काफी आसान है।

लेकिन, यदि संख्याओं में से कोई शून्य है तो क्या होगा?शून्य के मुकाबले तुलना करते समय रिश्तेदार मतभेदों या महत्वपूर्ण अंकों की पूरी अवधारणा गिर जाती है। उस मामले को संभालने के लिए आपको एक पूर्ण-अंतर भी होना चाहिए, जिसे सापेक्ष-अंतर से अलग निर्दिष्ट किया जाना चाहिए। शून्य से निपटने में किसी विशिष्ट मामले सहित - -

मैं की तुलना फ्लोटिंग प्वाइंट नंबर की समस्याओं पर चर्चा इस ब्लॉग पोस्ट में:

http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

31

अजगर 3.5 के रूप में, मानक तरीका यह है (मानक पुस्तकालय का उपयोग) math.isclose समारोह के साथ है।

यह निम्न हस्ताक्षर हैं:

isclose(a, b, rel_tol=1e-9, abs_tol=0.0) 

निरपेक्ष त्रुटि सहिष्णुता के साथ उपयोग का एक उदाहरण:

from math import isclose 
a = 1.0 
b = 1.00000001 
assert isclose(a, b, abs_tol=1e-8) 

आप इसे n सार्थक अंकों की परिशुद्धता के साथ चाहते हैं, बस की जगह अंतिम पंक्ति के साथ:

assert isclose(a, b, abs_tol=10**-n) 
संबंधित मुद्दे