2008-11-30 20 views
14

अभी तक मैंने फ़्लोटिंग पॉइंट नंबरों की समानता से निपटने वाली कई पोस्ट देखी हैं। एक सवाल का मानक जवाब जैसे "हम कैसे तय कर सकते हैं कि एक्स और वाई बराबर हैं?"क्या हमें * रिश्तेदार * त्रुटि के विरुद्ध समानता के लिए फ़्लोटिंग पॉइंट नंबरों की तुलना करनी चाहिए?

abs(x - y) < epsilon 

जहां एप्सिलॉन एक तय, छोटे स्थिर है है। ऐसा इसलिए है क्योंकि "ऑपरेंड" एक्स और वाई अक्सर कुछ गणना के परिणाम होते हैं जहां एक गोलाकार त्रुटि शामिल होती है, इसलिए मानक समानता ऑपरेटर == हमारा मतलब नहीं है, और हमें वास्तव में क्या पूछना चाहिए कि क्या x और y हैं बंद करें, बराबर नहीं।

अब, मुझे लगता है कि अगर एक्स वाई करने के लिए "लगभग बराबर" है, तो भी एक्स * 10^20 y * 10^20 "लगभग बराबर" होना चाहिए, इस अर्थ में कि रिश्तेदार त्रुटि होना चाहिए वही (लेकिन "रिश्तेदार" क्या है?)। लेकिन इन बड़ी संख्याओं के साथ, उपर्युक्त परीक्षण विफल हो जाएगा, यानी वह समाधान "स्केल" नहीं करता है।

आप इस मुद्दे से कैसे निपटेंगे? क्या हमें संख्याओं को पुन: सहेजना चाहिए या ईपीएसलॉन को पुन: सहेजना चाहिए? कैसे? (या मेरे अंतर्ज्ञान गलत क्या है?)

यहाँ एक related question है, लेकिन मैं अपने को स्वीकार कर लिया जवाब पसंद नहीं है, reinterpret_cast बात के लिए एक सा मेरे लिए मुश्किल लगता है, मुझे समझ नहीं आता क्या हो रहा है। कृपया एक सरल परीक्षण प्रदान करने का प्रयास करें।

उत्तर

17

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

This page फ्लोट की तुलना करने के लिए कई तकनीकों की रूपरेखा तैयार करता है। यह कई महत्वपूर्ण मुद्दों पर भी चला जाता है, जैसे उपनिवेश, infinities, और NaNs। यह एक महान पढ़ा है, मैं अत्यधिक माध्यम से इसे पढ़ने की सलाह देते हैं।

+0

धन्यवाद। पेपर भी कठोर कलाकारों के पीछे की प्रेरणा के बारे में बताता है (हालांकि सामान्य कोड में मैं समझदारी का चयन करता हूं और सभी फ्लोट समाधानों में से एक का उपयोग करता हूं :) –

+1

उपरोक्त लिंक का अद्यतन संस्करण है [फ्लोटिंग पॉइंट नंबर, 2012 संस्करण की तुलना करना] (http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/) – sfstewman

1

समस्या यह है कि बहुत बड़ी संख्या के साथ, ईपीएसलॉन की तुलना में असफल हो जायेगा।

div(max(a, b), min(a, b)) < eps + 1 

अब 'त्रुटि' सापेक्ष किया जाएगा:

शायद एक बेहतर (लेकिन धीमी) समाधान का उपयोग करने प्रभाग, उदाहरण होगा।

+0

निश्चित रूप से, यह ए और बी के बीच न्यूनतम से संबंधित है, है ना? –

+2

हम्म। शून्य से डिवीजनों से सावधान रहें :) –

+0

और उनके हस्ताक्षर पर ध्यान दें। आदम के जवाब में पेपर तुलनात्मक पूर्ण अधिकतम तुलना दर्शाता है। –

3

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

+0

गोल और छंटनी खराब काम करती है। यदि हम हास्यास्पद रूप से बंद होने के बावजूद तीन अंकों तक (निकटतम) गोल करते हैं तो 1.4 99 99 99 99 999 और 1.5000000000001 विज्ञापन की तुलना अलग-अलग करेंगे। अगर हम बहुत कम होने के बावजूद 1.99 99 99 99 99 99 और 2.00000000000001 को अलग करते हैं तो अलग-अलग तुलना करेंगे। किसी भी गोलाकार या छंटनी योजना के इस तरह के cusps होगा। किसी भी समाधान को संख्याओं को घटाकर और फिर निर्णय लेना शुरू करना है कि अलग-अलग महत्वपूर्ण होने के लिए पर्याप्त है या नहीं। –

+1

@ ब्रूसडॉसन 1.4 99 99 99 99 99 99 और 1.500000000000101 3 अंकों के लिए गोलाकार बराबर की तुलना करेंगे ... (दोनों 1.5) – colmde

+1

हू। मुझे यकीन नहीं है कि मैंने उन नंबरों को उदाहरण के रूप में क्यों दिया क्योंकि आप सही हैं, जैसा कि मैंने दावा किया है, वे काम नहीं करते हैं। वास्तविक समस्या यह है कि आपके पास दो मनमाने ढंग से करीबी संख्याएं हो सकती हैं जो एक-दूसरे से दूर हो जाती हैं और इसलिए जब उन्हें समान रूप से तुलना की जानी चाहिए तो अलग-अलग तुलना करें। निकटतम के लिए: 1.50500000000000001 1.50499999999999999 जब तीन अंकों तक गोल किया जाता है तो ये हमें 1.51 और 1.50 देते हैं, एक बिलियन से भी कम हिस्से से अलग होने के बावजूद। कोई भी गोल करने वाली योजना इस समस्या को कुसुआ के पास संख्याओं के साथ प्रभावित करेगी। यही कारण है कि दौर और तुलना टूट गई है। –

0

सापेक्ष त्रुटि का उपयोग कम से कम त्रुटियों का उपयोग करने जितना बुरा नहीं है, लेकिन गोल करने के मुद्दों के कारण शून्य के मानों के लिए सूक्ष्म समस्याएं हैं। एक दूर से सही, लेकिन कुछ हद तक मजबूत एल्गोरिथ्म निरपेक्ष को जोड़ती है और रिश्तेदार त्रुटि दृष्टिकोण:

boolean approxEqual(float a, float b, float absEps, float relEps) { 
    // Absolute error check needed when comparing numbers near zero. 
    float diff = abs(a - b); 
    if (diff <= absEps) { 
     return true; 
    } 

    // Symmetric relative error check without division. 
    return (diff <= relEps * max(abs(a), abs(b))); 
} 

मैं ब्रूस डावसन उत्कृष्ट लेख Comparing Floating Point Numbers, 2012 Edition, एक आवश्यक किसी को भी फ्लोटिंग प्वाइंट की तुलना करते समय के लिए पढ़ने से इस कोड को अनुकूलित - एक आश्चर्यजनक जटिल विषय कई नुकसान के साथ।

0

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

  1. तो मैं जानता हूँ कि वापस लौटे क्या एक समारोह जब एक्स का मान दिया, मैं यह मान सकते हैं, तो Y दिया यह एक ही बात वापस आ जाएगी: उदाहरण के लिए?

  2. यदि मेरे पास धीमे लेकिन सटीक फ़ंक्शन की गणना करने की कोई विधि है, तो मैं गति के बदले में कुछ गलतता स्वीकार करने के लिए तैयार हूं, और मैं एक उम्मीदवार फ़ंक्शन का परीक्षण करना चाहता हूं जो कि बिल फिट बैठता है, आउटपुट हैं उस कार्य से ज्ञात-सटीक को पर्याप्त "सही" माना जाना चाहिए।

पहले सवाल का जवाब करने के लिए, कोड आदर्श मूल्य पर थोड़ा-वार तुलना करना चाहिए, हालांकि जब तक कि एक भाषा है कि आदर्श की तुलना में कम कुशल हो सकता है 2009 में आईईईई-754 में जोड़े गए नए ऑपरेटरों का समर्थन करता है। दूसरे प्रश्न का उत्तर देने के लिए, किसी को परिभाषित करना चाहिए कि सटीकता की किस डिग्री की आवश्यकता है और उसके खिलाफ परीक्षण करें।

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

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