2016-06-04 10 views
8

मैं युगल indata कहा जाता है की एक सरणी (ढेर में, malloc साथ आवंटित) के साथ काम कर रहा हूँ, और एक स्थानीय डबल sum कहा जाता है।सी बुनियादी बातों: डबल चर डबल अभिव्यक्ति के बराबर नहीं है?

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

मेरे समारोह एक का उपयोग करता है:

if (indata[i]+indata[j] > max) hi++; 

और मेरे समारोह बी का उपयोग करता है:

sum = indata[i]+indata[j]; 
    if (sum>max) hi++; 

एक ही डेटा सेट और max अध्ययन करने के बाद मैं जो के आधार पर hi के विभिन्न मूल्यों के साथ खत्म मैं उपयोग करता हूँ समारोह। मेरा मानना ​​है कि फ़ंक्शन बी सही है, और फ़ंक्शन ए भ्रामक है। इसी प्रकार जब मैं

sum = indata[i]+indata[j]; 
    if ((indata[i]+indata[j]) != sum) etc. 

से नीचे स्निपेट का प्रयास करता है तो सशर्त सत्य का मूल्यांकन करेगा।

जबकि मैं समझता हूँ कि चल बिन्दु संख्या जरूरी बनाम एक चर में संग्रहीत एक सटीक प्रतिनिधित्व, क्यों कि इन-सही प्रतिनिधित्व परिवर्तन जब एक अभिव्यक्ति के रूप में मूल्यांकन करता है प्रदान नहीं करते हैं? एक सशर्त से पहले इस तरह की एक डबल अभिव्यक्ति का हमेशा मूल्यांकन करने के लिए सबसे अच्छा अभ्यास की सिफारिश की जाती है? धन्यवाद!

+0

यह मूल रूप से है क्योंकि कंप्यूटर की कुल परिशुद्धता के साथ संख्या का प्रतिनिधित्व नहीं कर सकता है। फ़्लोटिंग पॉइंट के बारे में पढ़ें। –

+0

@iharob उन्होंने स्वीकार किया कि उनके अंतिम अनुच्छेद में। लेकिन यह स्पष्ट नहीं करता है कि आप एक चर के परिणाम को निर्दिष्ट करते हैं या नहीं, इस पर निर्भर करता है कि यह अलग क्यों है। – Barmar

+0

क्या यह x86 या x86-64 के लिए संकलित है? – Dolda2000

उत्तर

12

मुझे संदेह है कि आप 32-बिट x86 का उपयोग कर रहे हैं, एकमात्र आम वास्तुकला अतिरिक्त परिशुद्धता के अधीन है। सी में, प्रकार float और double के भाव वास्तव में float_t या double_t के रूप में मूल्यांकन किए जाते हैं, जिनके संबंध float और double पर FLT_EVAL_METHOD मैक्रो में दिखाई देते हैं। 86 के मामले में, दोनों long double के रूप में क्योंकि एफपीयू वास्तव में एकल या डबल परिशुद्धता पर गणित करने में सक्षम नहीं है परिभाषित कर रहे हैं। एक ही रास्ता राउंडिंग मजबूर करने के लिए और अधिक से छुटकारा पाने के (ऐसा नहीं है कि अनुमति देने के लिए इरादा मोड बिट्स है, लेकिन व्यवहार में थोड़ा गलत है और इस तरह का प्रयोग नहीं किया जा सकता है।)

प्रकार float या double का एक उद्देश्य के लिए नियत है परिशुद्धता, लेकिन आप (double) पर एक gratuitous cast भी जोड़ सकते हैं यदि आप इसे असाइनमेंट के बिना अभिव्यक्ति के रूप में छोड़ना पसंद करते हैं।

ध्यान दें कि वांछित परिशुद्धता को गोल करने के लिए मजबूर करना वांछित परिशुद्धता पर अंकगणित करने के बराबर नहीं है; एक गोल करने के चरण (अंकगणितीय के दौरान) के पास अब आपके पास दो (अंकगणितीय के दौरान, और फिर अवांछित परिशुद्धता छोड़ने के लिए) हैं, और ऐसे मामलों में जहां पहला राउंडिंग आपको सटीक-मध्यबिंदु देता है, दूसरा दौर 'गलत' में जा सकता है ' दिशा। यह समस्या आम तौर पर डबल राउंडिंग कहा जाता है, और यह अतिरिक्त परिशुद्धता गणना के कुछ प्रकार के लिए नाममात्र परिशुद्धता की तुलना में काफी बदतर बना देता है।

+0

धन्यवाद। मैं 64-बिट विंडोज 7 चला रहे i7-3770 cpu पर कोड चला रहा हूं। हालांकि, मेरा कंपाइलर minGW है, जो 32 बिट एप्लिकेशन है। मैं कंपाइलर सेटिंग्स की जांच करेंगे। मैं समझता हूं कि डबल से अधिक सटीक हार्डवेयर स्तर है, और अभिव्यक्ति बनाम चर का उपयोग करने के साथ और अधिक सावधान रहेंगे। एफवाईआई, अभिव्यक्ति कास्टिंग टाइप करें वास्तव में इस मामले में काम नहीं करता है - इसके बिना वही व्यवहार। – stilllearning

+1

'-std = c99' या' -fexcess-precision = standard' के साथ कास्ट आज़माएं। कुछ गैर मानकों-अनुरूप मोड में जीसीसी को व्यवहार गलत हो जाता है। –

+0

धन्यवाद - इनमें से किसी भी कंपाइलर कमांड लाइन विकल्प समस्या को हल करता है, ताकि यह कोड सही तरीके से व्यवहार कर सके: 'अगर ((डबल) (indata [i] + indata [j])> max) hi ++; ' – stilllearning

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