2012-07-10 12 views
15

मैं एक स्ट्रिंग है कि मैं एक डबल में बदलने का इस तरह है:"-Weverything" उपज "== साथ चल बिन्दु या = असुरक्षित है की तुलना करना!"

double d = [string doubleValue]; 

doubleValue के लिए दस्तावेज़ कि अतिप्रवाह पर बताता है , यह विधि या तो HUGE_VAL या -HUGE_VAL देता है। इस तरह मैं के लिए जाँच की है इस:

if (d == HUGE_VAL || d == -HUGE_VAL) 
    //overflow 

अब, नई जोड़ने के बाद से "-Weverything" झंडा चेतावनी, संकलक अब शिकायत है कि

Comparing floating point with == or != is unsafe 

मैं कैसे इस समस्या को हल कर सकते हैं? कैसे मुझे यह तुलना करनी चाहिए?


मैं भी दो "सामान्य" चल बिन्दु संख्या (अर्थात नहीं "HUGE_VAL" वाले) की तुलना के बारे में एक ही सवाल है। उदाहरण के लिए,

double a, b; 
//... 
if (a != b) //this will now yield the same warning 
    //... 

इसे कैसे हल किया जाना चाहिए?

उत्तर

29

आप इस चेतावनी के बारे में चिंता करने की जरूरत नहीं है। यह आपके सहित कई मामलों में बकवास है।

doubleValue का प्रलेखन यह नहीं कहता है कि यह HUGE_VAL या -HUGE_VAL पर अतिप्रवाह पर पर्याप्त कुछ देता है। यह कहता है कि ओवरफ्लो के मामले में यह वास्तव में इन मानों को वापस कर देता है।

दूसरे शब्दों में, ओवरफ्लो की तुलना में विधि द्वारा लौटाया गया मान == से HUGE_VAL या -HUGE_VAL की तुलना में किया गया मान।

चेतावनी क्यों पहले स्थान पर मौजूद है?

उदाहरण पर विचार करें 0.3 + 0.4 == 0.7। यह उदाहरण झूठी का मूल्यांकन करता है। आपके द्वारा मुलाकात की गई चेतावनी के लेखकों सहित लोग सोचते हैं कि फ़्लोटिंग-पॉइंट == गलत है, और अप्रत्याशित परिणाम इस गलतता से आता है।

वे सभी गलत हैं।

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

फ़्लोटिंग-पॉइंट समानता, दूसरी तरफ, यह अन्य अलग-अलग प्रकार के लिए बिल्कुल ठीक तरह से काम करता है।फ़्लोटिंग-पॉइंट समानता सटीक है: मामूली अपवादों (NaN मान और +0 और -0 के मामले) को छोड़कर, समानता का मूल्यांकन सही होता है और केवल तभी होता है जब दोनों फ़्लोटिंग-पॉइंट संख्याओं के विचाराधीन समान प्रतिनिधित्व हो।

यदि आपको दो फ़्लोटिंग-पॉइंट मान बराबर हैं तो परीक्षण करने के लिए आपको एक ईपीएसलॉन की आवश्यकता नहीं है। और, Dewar says in substance के रूप में, 0.3 + 0.4 == 0.7 उदाहरण में चेतावनी + पर, == पर, चेतावनी के लिए चेतावनी के लिए होना चाहिए।

आखिरकार, एक ईपीएसलॉन के भीतर तुलना करने का अर्थ है कि मान जो बराबर नहीं हैं, वे समान दिखेंगे, जो सभी एल्गोरिदम के लिए उपयुक्त नहीं है।

+0

समझ में आता है। दूसरी ओर, यह कुछ तरीकों से इस बारे में चेतावनी देने के लिए भी समझ में आता है। क्या संकलक को अधिक स्पष्ट रूप से बताने का कोई तरीका है कि: "हां, मुझे पूरा यकीन है कि मैं इन फ्लोट्स की तुलना एक दूसरे के बराबर होने के समान कर रहा हूं, और मुझे चेतावनी न दें।" ? तो ऐसे मामलों में जहां मुझे यकीन है, चेतावनी प्रकट नहीं होगी। अन्य मामलों में, मैं ईपीएसलॉन परीक्षण करता हूं। – NoobOverflow

+0

@NoobOverflow यदि आप वास्तव में संकलक को खुश करना चाहते हैं, तो जांच करें कि 'd> = HUGE_VAL || डी <= -HUGE_VAL'। यह '==' का उपयोग किए बिना एक ही चीज़ की गणना करता है। लेकिन मैं चेतावनी का उपयोग नहीं करने की सलाह देते हैं। –

+0

@NoobOverflow असल में, मेरी पिछली सिफारिश कोड को कम पठनीय बनाता है, लेकिन यदि उद्देश्य-सी में 'is_infinity' फ़ंक्शन है, तो इसका उपयोग कोड ** अधिक ** पठनीय होगा। फ़ंक्शन का विनिर्देश यह होना चाहिए कि यह दो मानों 'HUGE_VAL' और '-HUGE_VAL' के लिए बिल्कुल सही है, और मैं अनुशंसा करता हूं कि आप इसका उपयोग केवल उसी के लिए करें। –

-1

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

यह ऐसा दिखाई दे सकता:

const float EPSILON = 1.0f; // use a really small number instead of this 

bool closeEnough(float f1, float f2) 
{ 
    return fabs(f1-f2)<EPSILON; 
    // test if the floats are so close together that they can be considered equal 
} 
+1

क्या एप्सिलॉन की सिफारिश की जा सकती है? क्या यह दृष्टिकोण उन HUGE_VALs के साथ भी काम करेगा? और, क्या आपका जवाब यह दर्शाता है कि ऊपर पास्कल की टिप्पणी गलत है? – NoobOverflow

+0

इसके अलावा, क्या ऐसा कोई अच्छा अंतर्निहित फ़ंक्शन नहीं है जिसका मैं उपयोग कर सकता हूं? यह दयालु है कि मुझे कुछ वैश्विक जगहों पर अपना खुद का कस्टम फ़ंक्शन टकरा देना है। – NoobOverflow

+0

पास्कल सही है, आपको शायद इस चेतावनी के बारे में चिंता करने की आवश्यकता नहीं होगी। हालांकि एक अंतर्निहित ईपीएसलॉन है, [इस] पर एक नज़र डालें (http://www.cplusplus.com/reference/std/limits/numeric_limits/) – Brainbot

8

इस मामले में, >= और <= का उपयोग करने का प्रयास करें।

+3

यह बेहतर क्यों है? –

+3

ठीक है, यह सख्त समानता की तुलना नहीं करता है, इसलिए यह संकलक को शांत करता है।और चूंकि कुछ भी HUGE_VAL से अधिक या HUGE_VAL से कम नहीं हो सकता है, यह वही काम करता है। – echristopherson

2

आप अपनी तुलना के बारे में निश्चित हैं और आप बजना करने के लिए कह चाहते हैं, के साथ अपने कोड के चारों ओर:

#pragma clang diagnostic ignored "-Wfloat-equal" 
/* My code triggering the warnings */ 
#pragma clang diagnostic pop