9

तो मैं एक समारोह है कि कुछ इस तरह दिखता है:किसी भी तरह चर बदल सकते हैं?

float function(){ 
    float x = SomeValue; 
    return x/SomeOtherValue; 
} 

कुछ बिंदु पर, इस समारोह अतिप्रवाह और एक बहुत बड़ी नकारात्मक मान देता है। कोशिश करते हैं और वास्तव में, जहां इस हो रहा था नीचे ट्रैक करने के लिए, मैं एक अदालत बयान जोड़ा ताकि समारोह इस तरह देखा:

float function(){ 
    float x = SomeValue; 
    cout << x; 
    return x/SomeOtherValue; 
} 

और यह काम किया! बेशक, मैंने डबल का उपयोग कर पूरी तरह से समस्या हल की। लेकिन मैं उत्सुक हूं कि जब मैंने इसे देखा तो फ़ंक्शन ठीक से क्यों काम करता था। क्या यह सामान्य है, या कहीं और एक बग हो सकता है कि मैं याद कर रहा हूँ?

(यह किसी भी मदद है, नाव में संग्रहीत मूल्य सिर्फ एक पूर्णांक मान है, और नहीं एक विशेष रूप से बड़ा है। मैं सिर्फ एक नाव में रख कास्टिंग से बचने के लिए।)

उत्तर

18

फ़्लोटिंग पॉइंट की अद्भुत दुनिया में आपका स्वागत है। आपके द्वारा प्राप्त उत्तर की संभावना आपके द्वारा कोड को संकलित करने वाले फ़्लोटिंग पॉइंट मॉडल पर निर्भर करेगी।

यह आईईईई स्पेक और हार्डवेयर के बीच के अंतर के कारण होता है क्योंकि कोड चल रहा है। आपके सीपीयू में 80 बिट फ़्लोटिंग पॉइंट रजिस्ट्रार हैं जो 32-बिट फ्लोट वैल्यू को पकड़ने के लिए उपयोग करते हैं। इसका मतलब यह है कि मूल्य अधिक सटीक है जबकि मूल्य एक रजिस्टर में रहता है जब इसे स्मृति पते पर मजबूर किया जाता है (जिसे रजिस्टर 'होमिंग' भी कहा जाता है)।

जब आप कोटेर के मूल्य को पारित करते हैं तो संकलक को फ्लोटिंग पॉइंट को स्मृति में लिखना पड़ता था, और इसके परिणामस्वरूप परिशुद्धता और रोचक व्यवहार डब्लूआरटी अतिप्रवाह मामलों के खो गए।

वीसी ++ floating point switches पर एमएसडीएन दस्तावेज देखें। आप/fp के साथ संकलन करने का प्रयास कर सकते हैं: सख्त और देखकर क्या होता है।

+0

http://gcc.gnu.org/wiki/x87note पर इस के लिए एक जीसीसी नोट भी है, इस अद्भुत व्यवहार के कारण, फ़्लोटिंग पॉइंट कंप्यूटेशंस की तुलना करना भी पूर्व-गणना मूल्यों का उपयोग करते समय स्वाभाविक रूप से टूटा हुआ है। – hazzen

3

एक मूल्य के मुद्रण अदालत को किसी भी तरह से पैरामीटर के मूल्य को नहीं बदलना चाहिए।

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

कोउट कथन जोड़ना मतलब है कि एक्स का वाउ सीधे उपयोग किया जाता है। इसके बिना अनुकूलक चर को हटा सकता है, इसलिए गणना के क्रम को बदल रहा है और इसलिए उत्तर बदल रहा है।

0

मुझे नहीं लगता कि कोउट का चर पर कोई प्रभाव पड़ता है, समस्या कहीं और होनी चाहिए।

2

एक अलग रूप में के रूप में, यह हमेशा एक अच्छा विचार है const का उपयोग कर अपरिवर्तनीय चर घोषित करने के लिए:

float function(){ 
    const float x = SomeValue; 
    cout << x; 
    return x/SomeOtherValue; 
} 

अन्य बातों के इस अनजाने कार्यों के लिए अपने चर गुजर से रोकेंगी के अलावा है कि उन्हें गैर const संदर्भ के माध्यम से संशोधित कर सकते हैं ।

1

cout चर के संदर्भ का कारण बनता है, जो अक्सर संकलक को इसे ढेर तक फैलाने के लिए मजबूर कर देगा।

क्योंकि यह एक फ्लोट है, यह संभवतः इसके मूल्य को डबल या लंबे डबल प्रतिनिधित्व से छोटा कर दिया जाएगा।

किसी भी फ़ंक्शन (गैर-रेखांकित) को कॉल करना जो एक्स के लिए सूचक या संदर्भ लेता है, उसी व्यवहार के कारण समाप्त होना चाहिए, लेकिन यदि संकलक बाद में समझदार हो जाता है और इसे रेखांकित करना सीखता है, तो आप समान रूप से खराब हो जाएंगे :)

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