2010-10-12 17 views
6

यदि foo फ्लोट प्रकार का है, तो निम्न अभिव्यक्ति वैध/अनुशंसित है?फ़्लोटिंग-पॉइंट की तुलना 0

(0.0f == foo * float(0)) 

क्या यह foo के मूल्य के बावजूद अपेक्षित (गणितीय) मूल्य होगा?

क्या सी ++ मानक व्यवहार को परिभाषित करता है या यह कार्यान्वयन विशिष्ट है?

+0

यह डिबग करने के लिए प्रयास करें।। यही कारण है कि काम करने वाला नहीं है: – rkellerm

+0

@ rursw1 अधिक मानक – CsTamas

+0

से एक गारंटी @ rursw1 वहाँ अगर दिलचस्पी। –

उत्तर

2

AFAIK, यह जरूरी नहीं कि, यह भी ऊपर बहुत 0.

के करीब खत्म हो सकता है जाएगा यह आम तौर पर एक एप्सिलॉन के खिलाफ तुलना करने के लिए सबसे अच्छा है। मैं इस तरह की तुलना करने के लिए इस तरह एक समारोह का उपयोग करें:

float EpsilonEqual(float a, float b, float epsilon) 
{ 
    return fabsf(a - b) < epsilon; 
} 
+0

@Armen: आप बिल्कुल सही अपने fabsf :) – Goz

+1

आईईईई 754 जनादेश कि -0.0f == + 0.0f, भले ही थोड़ा मान भिन्न हैं कर रहे हैं। –

+0

@ माइकल: पर्याप्त मेला। हालांकि बिंदु से अलग नहीं है। हालांकि मैं संदर्भ हटा दूंगा। – Goz

3

खैर, सबसे पहले यह वास्तव में सी ++ मानक की बात नहीं है। इसके बजाय समस्या पर क्या है आपका फ़्लोटिंग-पॉइंट मॉडल मानक (सबसे अधिक संभावना आईईईई)।

आईईईई फ्लोट्स के लिए, यह संभवतः सुरक्षित है, क्योंकि float(0) के परिणामस्वरूप 0.0f के समान संख्या होनी चाहिए, और किसी भी अन्य संख्या से गुणा किया जाना चाहिए 0.0f भी होना चाहिए।

अन्य फ़्लोटिंग पॉइंट ऑप्स (उदाहरण: गैर-पूर्ण संख्याओं के साथ जोड़ता है और घटाता है) और वास्तव में 0.0f के खिलाफ जांच कर रहा है।

+6

शून्य से किसी भी सीमित आईईईई मूल्य को गुणा करने से शून्य मिलेगा। यदि 'foo' अनंत या NaN है, तो गुणा परिणाम NaN है, और तुलना परिणाम गलत है। –

+0

@ माइक सेमुर - अच्छा बिंदु। शायद वह लाइन एक जांच के लिए थी कि foo एक मान्य फ्लोट मान है। –

1
कि विशेष रूप से बयान के साथ

, तो आप यकीन है कि परिणाम 0 हो जाएगा हो सकता है और तुलना true हो - मुझे नहीं लगता कि सी ++ मानक वास्तव में यह प्रावधान है, लेकिन चल बिन्दु प्रकार के किसी भी उचित कार्यान्वयन 0 काम की तरह होगा उस।

हालांकि, ज्यादातर अन्य गणना के लिए, परिणाम नहीं वास्तव में गणितीय सही परिणाम की एक शाब्दिक के बराबर होने की उम्मीद की जा सकती है:

क्यों नहीं मेरी नंबर, जैसे 0.1 + 0.2 ऐड एक अच्छा दौर 0.3, और के बजाय मुझे 0.30000000000000004 जैसे अजीब परिणाम मिलते हैं?

क्योंकि आंतरिक रूप से, कंप्यूटर एक प्रारूप (बाइनरी फ्लोटिंग प्वाइंट) कि सही ढंग से सब पर 0.1, 0.2 या 0.3 की तरह एक नंबर का प्रतिनिधित्व नहीं कर सकते हैं का उपयोग करें।

जब कोड संकलित किया गया है या व्याख्या की, अपने "0.1" पहले से ही कि प्रारूप में निकटतम संख्या है, जो एक छोटे से में जो परिणाम त्रुटि गोलाई से पहले ही गणना होता है गोल है।

पढ़ें The Floating-Point Guide विस्तृत व्याख्या और कैसे comparisons with expected values सही ढंग से करने के लिए।

0

मैं सिर्फ इस लेख MSDN में/fp विकल्प के बारे में VisualStudio में पढ़ link text

अभिव्यक्ति अनुकूलन नहीं है जो विशेष मूल्यों (NaN के लिए अमान्य हैं, + अनंत, -infinity, +0, -0) की अनुमति नहीं दी जाएगी।अनुकूलन xx => 0, x * 0 => 0, एक्स-0 => एक्स, एक्स + 0 => एक्स, और 0-एक्स => -x हैं विभिन्न कारणों (आईईईई 754 को देखने के लिए सभी अमान्य और सी 99 मानक)।

+0

मुझे लगता है कि यहां टिप्पणी केवल इस तथ्य का जिक्र कर रही है कि एक्स * 0 NaN है यदि एक्स NaN है। – hobbs

2

NaNs और Infinites इस तरह की तुलनाओं को खराब कर सकते हैं, जैसा कि अन्य ने पहले ही उल्लेख किया है।

हालांकि, वहाँ आगे ख़तरा है: C++ आप, नाव प्रकार का एक संकलन समय अभिव्यक्ति पर भरोसा नहीं कर सकते एक ही अभिव्यक्ति रन टाइम पर मूल्यांकन किया जाता के बराबर की तुलना।

उस के लिए कारण यह है कि सी ++ fp संगणना के लिए विस्तारित परिशुद्धता की अनुमति देता है, किसी भी बिना सोचे समझे तरीके से है। उदाहरण:

एक विशेष संकलक साथ
#include <iostream> 

// This provides sufficent obfuscation so that g++ doesn't just inline results. 
bool obfuscatedTrue() { return true; } 

int main() 
{ 
    using namespace std; 

    double const a = (obfuscatedTrue()? 3.0 : 0.3); 
    double const b = (obfuscatedTrue()? 7.0 : 0.7); 
    double const c = a/b; 

    cout << (c == a/b? "OK." : "\"Wrong\" comparision result.") << endl; 
} 

परिणाम:

C:\test> g++ --version | find "++" 
g++ (TDM-2 mingw32) 4.4.1 

C:\test> g++ fp_comparision_problem.cpp & a 
"Wrong" comparision result. 

C:\test> g++ -O fp_comparision_problem.cpp & a 
OK. 

C:\test> _ 

चीयर्स & hth,

- Alf

+0

क्या उच्च परिशुद्धता में आप को डर है कि 'foo * नाव (0) का परिणाम' गुणा प्रकार की शुद्धता पर किए गए कार्य का परिणाम से अलग हो सकता हैं? –

+0

क्या कंपेलरों को उन परिणामों के अलावा अन्य परिणाम देने की अनुमति देने की कोई उपयोगीता है जो तुलना ऑपरेटरों के ऑपरेटरों को उनके संकलन-समय प्रकारों (जैसे 'someFloat == अन्य फ़्लोट/3.0 एफ' को मूल्यांकन करने की इजाजत देते हैं) '(डबल) कुछ फ्लोट == (डबल) अन्य फ्लोट/3.0')? ऐसा लगता है कि अधिकांश मामलों में जहां उत्तरार्द्ध "तेज़" है, यह भी बेकार परिणाम देगा। – supercat

+0

@ पास्कल क्यूओक: एस्वर में आउटपुट के साथ एक पूर्ण एक्सकंपल होता है। और इसलिए यह विचार है कि यह ऐसा कुछ है जिसे मैं "डर" कर सकता हूं, ऐसा लगता है कि आपने जवाब नहीं पढ़ा है। इसलिए, मैं सुझाव देता हूं कि आप करते हैं। –

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