2015-03-04 15 views
7

में अलग-अलग परिणाम निम्न प्रोग्राम (here से अनुकूलित) जीसीसी (4.8.2) और क्लैंग (3.5.1) के साथ संकलित होने पर असंगत परिणाम दे रहा है। विशेष रूप से, FLT_EVAL_METHOD करता है, भले ही जीसीसी परिणाम परिवर्तित नहीं होता है।वही FLT_EVAL_METHOD, जीसीसी/क्लैंग

#include <stdio.h> 
#include <float.h> 

int r1; 
double ten = 10.0; 

int main(int c, char **v) { 
    printf("FLT_EVAL_METHOD = %d\n", FLT_EVAL_METHOD); 
    r1 = 0.1 == (1.0/ten); 
    printf("0.1 = %a, 1.0/ten = %a\n", 0.1, 1.0/ten); 
    printf("r1=%d\n", r1); 
} 

टेस्ट:

$ gcc -std=c99 t.c && ./a.out 
FLT_EVAL_METHOD = 0 
0.1 = 0x1.999999999999ap-4, 1.0/ten = 0x1.999999999999ap-4 
r1=1 

$ gcc -std=c99 -mpfmath=387 t.c && ./a.out 
FLT_EVAL_METHOD = 2 
0.1 = 0x0.0000000000001p-1022, 1.0/ten = 0x0p+0 
r1=1 

$ clang -std=c99 t.c && ./a.out 
FLT_EVAL_METHOD = 0 
0.1 = 0x1.999999999999ap-4, 1.0/ten = 0x1.999999999999ap-4 
r1=1 

$ clang -std=c99 -mfpmath=387 -mno-sse t.c && ./a.out 
FLT_EVAL_METHOD = 2 
0.1 = 0x0.07fff00000001p-1022, 1.0/ten = 0x0p+0 
r1=0 

ध्यान दें कि, this blog post के अनुसार, जीसीसी 4.4.3 दूसरे टेस्ट में के बजाय उत्पादन 0 1 हुआ करता था।

possibly related question इंगित करता है कि जीसीसी 4.6 में एक बग को सही किया गया है, जो बता सकता है कि जीसीसी का परिणाम अलग क्यों है।

मैं यह पुष्टि करना चाहता हूं कि इनमें से कोई भी परिणाम गलत होगा या यदि कुछ सूक्ष्म मूल्यांकन कदम (जैसे एक नया प्रीप्रोसेसर ऑप्टिमाइज़ेशन) इन कंपाइलरों के बीच अंतर को औचित्य देगा।

+2

मुझे हाल ही में पुराने जीसीसी संस्करणों के व्यवहार की जांच करनी है और किसी ने मुझे https://gcc.godbolt.org पर इंगित किया जो बहुत उपयोगी था। इसमें जीसीसी 4.4.3 नहीं है, लेकिन इसमें 4.4.7 है। –

उत्तर

6

यह जवाब है, कुछ है कि आप इससे पहले कि आप आगे जाना समाधान हो जाना चाहिए के बारे में है, क्योंकि यह क्या बहुत कठिन नहीं तो क्या होता है के बारे में तर्क बनाने के लिए जा रहा है:

निश्चित रूप से मुद्रण 0.1 = 0x0.07fff00000001p-1022 या 0.1 = 0x0.0000000000001p-1022 केवल अपने संकलन मंच पर एक बग हो सकता है -mfpmath=387 का उपयोग करते समय एबीआई विसंगति के कारण। इन मूल्यों में से कोई भी अतिरिक्त परिशुद्धता से क्षमा नहीं किया जा सकता है।

आप परीक्षण फ़ाइल में अपना स्वयं का रूपांतरण-टू-पठनीय-प्रारूप शामिल करने का प्रयास कर सकते हैं, ताकि रूपांतरण को -mfpmath=387 से संकलित किया जा सके। या किसी अन्य फ़ाइल में एक छोटा सा ठूंठ बना, उस विकल्प के साथ संकलित नहीं, एक minimalistic कॉल सम्मेलन के साथ:

अन्य फ़ाइल में:

double d; 
void print_double(void) 
{ 
    printf("%a", d); 
} 

फ़ाइल में -mfpmath=387 साथ संकलित:

extern double d; 
d = 0.1; 
print_double(); 
+0

दरअसल, पहले 'print_double' फ़ाइल को' -mfpmath = 387' के बिना संकलित करना, और उसके बाद दूसरी फ़ाइल में '.o' को लिंक करना समस्या हल करता है: यह दोनों कंपाइलरों में' 0x1.999999999999ap-4' प्रिंट करता है, बिना और बिना '-mfpmath = 387' ध्वज। – anol

+0

मैंने अधिक पठनीय/ – CuriosGuy

+0

@CuriosGuy बनाने के लिए उत्तर संपादित किया है नोट करें कि आपके द्वारा उपयोग की जाने वाली शैली, इनलाइन बैकटिक्स '\' 'के साथ प्राप्त की गई है, ** कोड ** के लिए है।ओटीओएच प्रोग्राम आउटपुट के लिए कोई सिफारिश नहीं है, इसलिए शायद यहां स्वीकार्य है (लेकिन जोर के लिए '\' 'का उपयोग न करें)। –

0

printf समस्या को अनदेखा करते हुए, जिसे पास्कल कुओक ने संबोधित किया, मुझे लगता है कि जीसीसी सही है: सी 99 मानक के अनुसार, FLT_EVAL_METHOD == 2

long double प्रकार की सीमा और परिशुद्धता के लिए सभी परिचालनों और स्थिरांक का मूल्यांकन करें।

तो, इस मामले में, 0.1 और 1.0/ten दोनों 1/10 की एक विस्तारित परिशुद्धता सन्निकटन के लिए मूल्यांकन किया जा रहा है।

मुझे यकीन नहीं है कि क्लैंग क्या कर रहा है, हालांकि this question कुछ मदद प्रदान कर सकता है।

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