2012-06-13 15 views
10

मैंने देखा है कि फ़्लोटिंग-पॉइंट गणना गणना के विषय पर बहुत सी चर्चा है जिसके लिए आपको == से अधिक जटिल तुलना करने की आवश्यकता है। हालांकि, ये सभी लेख मानते हैं कि मूल्य किसी भी तरह से छेड़छाड़ (या दोहरी गणना) है, जबकि मुझे एक बहुत ही सरल निरंतर प्रतिलिपि को कवर करने वाला एक उदाहरण नहीं मिला।'कॉन्स' डबल कॉपीिंग + तुलना सुरक्षित है?

कृपया निम्नलिखित पर विचार:

const double magical_value = -10; 

class Test 
{ 
    double _val; 

public: 
    Test() 
     : _val(magical_value) 
    { 
    } 

    bool is_special() 
    { 
     return _val == magical_value; 
    } 
}; 

जहाँ तक मुझे इस बात को समझ के रूप में, magical_value, संकलन समय पर सेट किया जाना चाहिए, ताकि सभी राउंडिंग उस बिंदु पर होता है। इसके बाद, मूल्य को कक्षा में कॉपी किया जाना चाहिए, और मूल की तुलना में। क्या ऐसी तुलना सुरक्षित होने की गारंटी है? या या तो यहां त्रुटियों की प्रतिलिपि बना या तुलना कर सकते हैं?

कृपया वैकल्पिक तुलना या जादुई मूल्य उपयोग विधियों का सुझाव न दें, यह एक और विषय है। मैं इस धारणा के बारे में सिर्फ उत्सुक हूँ।

संपादित: सिर्फ नोट करने के लिए, मैं एक छोटे से डर है कि कुछ आर्किटेक्चर पर, अनुकूलन एक अलग तरह से आकार फ्लोटिंग प्वाइंट रजिस्टर करने के लिए मूल्य को कॉपी, इस प्रकार सटीक मान में मतभेद शुरू हो सकती थी हूँ। क्या ऐसा कुछ जोखिम है?

+0

रनटाइम के दौरान '_val' का मान बदला जाएगा? –

+0

हां, इसे वास्तविक मूल्य में बदला जा सकता है (फिर भी निश्चित रूप से '> -1')। मुझे यकीन नहीं है कि इसे वापस 'रीसेट' करने की आवश्यकता होगी या नहीं। –

+1

मुझे उम्मीद है कि एक फ्लोटिंग पॉइंट वैल्यू की प्रतिलिपि इसे बिल्कुल बदल नहीं पाएगी, और उसी प्रकार के दो चर 'ए' और' बी 'दिए गए हैं,' ए = बी 'परिणाम' ए == बी ' सच होना हालांकि, मैं इस धारणा को सामान्य ज्ञान पर आधारित कर रहा हूं, जो मुझे अतीत में जाने के लिए जाना जाता है। – Rook

उत्तर

2

क्या ऐसी तुलना सुरक्षित होने की गारंटी है? या या तो यहां त्रुटियों की प्रतिलिपि बना या तुलना कर सकते हैं?

हां, सुरक्षित (यह कॉपी ऑपरेशन की आवश्यकता है जैसा कि = द्वारा निहित है)। ऐसे कोई रूपांतरण/प्रचार नहीं हैं जिनके बारे में आपको चिंता करने की आवश्यकता है जब तक स्रोत और गंतव्य प्रकार समान हों।

हालांकि, ध्यान दें कि magical_value में 10 बिल्कुल नहीं बल्कि अनुमान लगाया जा सकता है। यह अनुमान _val पर कॉपी हो जाएगा।

const क्वालीफायर को देखते हुए, संभावना है कि magical_value शायद ऑप्टिमाइज़ किया जाएगा (आपको ऑप्टिमाइज़ेशन चालू करना चाहिए) या जैसा कि उपयोग किया जाता है (यानी कोई स्मृति शायद उपयोग नहीं की जाएगी)।

+3

मुझे अत्यधिक संदेह है कि एक कार्यान्वयन है जहां '10' या' -10' बिल्कुल 'डबल' के रूप में प्रस्तुत नहीं किया जा सकता है। – Henrik

+1

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

+0

@ हेनरिक: यह मूल्य 10 के बारे में नहीं है। इसके अलावा, बहुत से लोग इस तथ्य को अनदेखा करते हैं कि फ़्लोटिंग पॉइंट प्रकार मंटिसा-एक्सपोनेंट आधारित प्रतिनिधित्व का उपयोग करते हैं। – dirkgently

0

अलावा संभवतः अलग आकार के रजिस्टरों से, आप फ्लोटिंग बिंदु denormalized है (सीक्यू फ्लश करने वाली शून्य) के बारे में चिंता करने की (Why does changing 0.1f to 0 slow down performance by 10x? देखें)

बस weirdness इस का कारण बन सकता की एक विचार देने के लिए, कोशिश कोड के इस बिट:

float  a = 0.000000000000000000000000000000000000000047683384; 
const float b = 0.000000000000000000000000000000000000000047683384; 
float aa = a, bb = b; 

#define SUPPORT_DENORMALIZATION ({volatile double t=DBL_MIN/2.0;t!=0.0;}) 

printf("support denormals: %d\n",SUPPORT_DENORMALIZATION); 
printf("a = %.48f, aa = %.48f\na==aa %d, a==0.0f %d, aa==0.0f %d\n",a,aa,a==aa,a==0.0f,aa==0.0f); 
printf("b = %.48f, bb = %.48f\nb==bb %d, b==0.0f %d, bb==0.0f %d\n",b,bb,b==bb,b==0.0f,bb==0.0f); 

जो या तो देता है: (बिना फ्लश-टू-जीरो संकलित)

support denormals: 1 
a = 0.000000000000000000000000000000000000000047683384, aa = 0.000000000000000000000000000000000000000047683384 
a==aa 1, a==0.0f 0, aa==0.0f 0 
b = 0.000000000000000000000000000000000000000047683384, bb = 0.000000000000000000000000000000000000000047683384 
b==bb 1, b==0.0f 0, bb==0.0f 0 

या: (gcc -ffast-math साथ संकलित)

support denormals: 0 
a = 0.000000000000000000000000000000000000000000000000, aa = 0.000000000000000000000000000000000000000000000000 
a==aa 1, a==0.0f 1, aa==0.0f 1 
b = 0.000000000000000000000000000000000000000047683384, bb = 0.000000000000000000000000000000000000000000000000 
b==bb 1, b==0.0f 0, bb==0.0f 1 

कहाँ कि अंतिम पंक्ति निश्चित रूप से अजीब एक है बाहर: b==bb && b!=0.0f && bb==0.0f सच होगा।

तो यदि आप अभी भी फ़्लोटिंग पॉइंट मानों की तुलना करने के बारे में सोच रहे हैं, कम से कम छोटे मूल्यों से दूर रहें।

अद्यतन युगल के बजाय तैरता के उपयोग के कारण इस किया जा रहा है के बारे में कुछ टिप्पणियां की भरपाई के लिए, यह भी डबल के लिए काम करता है, लेकिन आप, DBL_MIN कहीं नीचे करने के लिए लगातार सेट करने के लिए जैसे की आवश्यकता होगी 1e-309

अपडेट 2 नीचे दी गई कुछ टिप्पणियों से संबंधित कोड नमूना। इससे पता चलता है कि इस समस्या को युगल के लिए मौजूद है और साथ ही, इसलिए तुलना करना असंगत हो सकता है कि (जब शून्य करने के लिए फ्लश सक्षम किया गया है)

double a; 
    const double b = 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001225; 
    const double c = 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002225; 

    printf("b==c %d\n",b==c); 
    a = b; 
    printf("assigned a=b: a==b %d\n",a==b); 
    a = c; 
    printf("assigned a=c: a==b %d\n",a==b); 

उत्पादन:

b==c 0 
assigned a=b: a==b 1 
assigned a=c: a==b 1 

मुद्दा अंतिम पंक्ति है, जहां में से पता चलता आप c!=b के साथ a=c असाइन करने के बाद a==b को स्पष्ट रूप से उम्मीद करेंगे।

+0

-1। मेरे उत्तर में मेरी टिप्पणी देखें। मैंने कोड के इस टुकड़े के साथ पहले से ही पर्याप्त मुद्दों को इंगित किया है। मैं वास्तव में उस बिंदु को नहीं देखता जिसे आप साबित करने की कोशिश कर रहे हैं। – dirkgently

+0

@ dirkgently दोस्त, आराम करो। मुद्दा यह है: ओपी का विचार है कि फ़्लोटिंग पॉइंट में कुछ छिपी हुई "विशेषताएं" हो सकती हैं। – mvds

+0

मुझे नहीं लगता कि यह एक समस्या है। आपके सभी परीक्षणों में, 'a == aa' और 'b == bb' सत्य थे, तो ओपी क्या कर रहा है सुरक्षित है। शून्य के साथ तुलना करते समय आपने कुछ विसंगतियों को दिखाया था, लेकिन ओपी क्या कर रहा है उससे यह एक अलग मुद्दा है। – interjay

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