2012-11-26 20 views
6

यदि मैं विंडोज़ और लिनक्स (उबंटू) पर निम्नलिखित सी लाइनों को संकलित करता हूं तो मुझे अलग-अलग परिणाम मिलते हैं। मैं टालना चाहूंगा। मैं यह कैसे कर सकता हूं?विभिन्न प्रणालियों पर समान फ्लोट नंबर कैसे सुनिश्चित करें?

double a = DBL_EPSILON; 
double b = sqrt(a); 
printf("eps = %.20e\tsqrt(eps) = %.20e\n", a, b); 

linux उत्पादन:

eps = 2.22044604925031308085e-16  sqrt(eps) = 1.49011611938476562500e-08 

खिड़कियों उत्पादन:

eps = 2.22044604925031310000e-016  sqrt(eps) = 1.49011611938476560000e-008 

32-बिट और 64-बिट सिस्टम एक ही परिणाम पर जीसीसी और बजना के साथ परीक्षण किया linux पर। 32-बिट और जी-बिट और 64-बिट के साथ विजुअल-स्टूडियो पर जीसीसी-मिंगव के साथ परीक्षण की गई विंडोज़ पर भी एक ही परिणाम।

+0

प्रत्येक सिस्टम की अंतर्निहित वास्तुकला क्या है? – Mike

+4

प्रयुक्त सी पुस्तकालयों के 'printf' कार्यान्वयन अलग-अलग हैं। विंडोज़ केवल 17 महत्वपूर्ण अंक प्रिंट करता है, और यदि अधिक अनुरोध किया जाता है तो शून्य के साथ भर जाता है। glibc प्रिंट सही ढंग से गोल मूल्य मुद्रित करता है। –

+0

लेकिन मेरे लिए ऐसा नहीं लगता है कि यह प्रिंटिंग का एक मुद्दा है, मेरा संख्यात्मक एल्गोरिदम भी थोड़ा अलग परिणाम देता है। और मैंने इस पंक्तियों की ओर इशारा किया, क्योंकि मुझे लगता है कि वे अंतर का स्रोत हैं। # – Will

उत्तर

9

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


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

लिनक्स पर, मानते हुए कि आप जीसीसी का उपयोग कर रहे हैं, -msse2 संकलन विकल्प आज़माएं। संपादित करें: ओपी ने टिप्पणी की कि -msse2 -mfpmath=sse उसके लिए काम किया है। इससे जीसीसी आधुनिक एसएसई 2 निर्देश उत्पन्न करता है जो सटीक आईईईई 754 फ्लोटिंग-पॉइंट अर्थशास्त्र प्रदान करता है। यदि विंडोज़ पर आप जीसीसी का भी उपयोग कर रहे हैं, तो उसी विकल्प का उपयोग करें।

आप विज़ुअल सी उपयोग कर रहे हैं: विज़ुअल सी एक और चाल का उपयोग करता है आईईईई 754 अर्थ विज्ञान मैच के लिए ऐतिहासिक फ्लोटिंग प्वाइंट निर्देश मजबूर करने के लिए: यह आईईईई के रूप में केवल के रूप में कई significand बिट का उपयोग करने के लिए पुराने 80-बिट फ्लोटिंग प्वाइंट हार्डवेयर बताता है 754 डबल-परिशुद्धता है। इससे कुछ कोने के मामलों को छोड़कर, डबल-परिशुद्धता संख्याओं का सटीक सिमुलेशन मिलता है जिन्हें आप सामना नहीं करेंगे। इस मामले में यह मदद करेगा (*) यदि आपका प्रोग्राम केवल डबल-सटीक संख्याओं का उपयोग करता है (सी double प्रकार)।

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

+1

मुझे नहीं पता कि मैं ओवरफ़्लो और अंडरफ्लो को कॉल करूंगा "कोने केस [एस] कि आप नहीं होंगे सामना "; वे वास्तविक कोड में अक्सर आश्चर्यजनक होते हैं। –

+0

@ स्टीफन कैनन आपने मुझे पकड़ा, शायद मैं पूरी तरह से ईमानदार नहीं हो सकता: अंडरफ्लो और ओवरफ़्लो हो सकता है। मेरी समस्या यह है कि अगर ऐसा होता है तो मेरे पास प्रस्ताव देने का कोई समाधान नहीं है, प्रोग्राम में मैन्युअल रूप से डालने से कम, हर जगह वे हो सकते हैं, 'intermediate_result = intermediate_result> = 0x1.0p + 1024? inf: intermediate_result; '। और कहानी अंडरफ्लो के लिए भी बदतर है, जिसके लिए मुझे महत्व को कम करने के लिए कोई ** पोर्टेबल ** कोड नहीं दिख रहा है। यदि प्रोग्रामर जानता है कि वह x87 का उपयोग कर रहा है, तो 'ldexp()' को दो कॉल करना चाहिए, लेकिन यह आईईईई 754 हार्डवेयर –

+0

@StephenCanon पर शून्य पर शून्य हो जाएगा, साथ ही, "ldexp()' समाधान के लिए दो कॉल डबल राउंडिंग –

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