मैं एक सिमुलेशन प्रोग्राम लिख रहा हूं जो अलग-अलग चरणों में आगे बढ़ता है। अनुकरण में कई नोड्स होते हैं, जिनमें से प्रत्येक के साथ एक फ्लोटिंग-पॉइंट मान होता है जिसे प्रत्येक चरण पर फिर से गणना की जाती है। नतीजा सकारात्मक, नकारात्मक या शून्य हो सकता है।फ्लोट्स का उपयोग करते समय मैं लगातार प्रोग्राम व्यवहार कैसे प्राप्त कर सकता हूं?
उस स्थिति में जहां परिणाम शून्य या उससे कम होता है। अभी तक यह स्पष्ट लगता है - मैं तो बस प्रत्येक नोड के लिए कुछ इस तरह कर सकते हैं:
if (value <= 0.0f) something_happens();
एक समस्या उत्पन्न हो गई है, फिर भी, मैं इस कार्यक्रम जिसमें मैं फिर से व्यवस्थित किया आदेश में किए गए कुछ हाल के परिवर्तन के बाद, जिसमें कुछ गणना की जाती है। एक परिपूर्ण दुनिया में इस पुनर्गठन के बाद मूल्य अभी भी समान होंगे, लेकिन फ्लोटिंग पॉइंट प्रस्तुति के अपर्याप्त होने के कारण वे बहुत अलग हैं। चूंकि प्रत्येक चरण की गणना पिछले चरण के परिणामों पर निर्भर करती है, इसलिए परिणामों में ये मामूली विविधता सिमुलेशन आय के रूप में बड़ी विविधताओं में जमा हो सकती है।
float f1 = 0.000001f, f2 = 0.000002f;
f1 += 0.000004f; // This part happens first here
f1 += (f2 * 0.000003f);
printf("%.16f\n", f1);
f1 = 0.000001f, f2 = 0.000002f;
f1 += (f2 * 0.000003f);
f1 += 0.000004f; // This time this happens second
printf("%.16f\n", f1);
इस कार्यक्रम का उत्पादन
0.0000050000057854
0.0000050000062402
है भले ही इसके विनिमेय इसलिए दोनों परिणाम एक ही होना चाहिए है:
यहाँ एक सरल उदाहरण कार्यक्रम है कि घटना को दर्शाता है मैं वर्णन कर रहा हूँ है । नोट: मैं पूरी तरह से समझता हूं कि यह क्यों हो रहा है - यह मुद्दा नहीं है। समस्या यह है कि इन भिन्नताओं का अर्थ यह हो सकता है कि कभी-कभी एक मान जो चरण एन पर नकारात्मक हो जाता है, कुछ_happens() को ट्रिगर करता है, अब पहले या बाद में एक या दो नकारात्मक नकारात्मक हो सकता है, जो समग्र सिमुलेशन परिणामों को बहुत अलग कर सकता है क्योंकि something_happens() का एक बड़ा प्रभाव है।
मैं क्या जानना चाहता हूं कि यह तय करने का एक अच्छा तरीका है कि कुछ_happens() को ट्रिगर किया जाना चाहिए जो गणना परिणामों में छोटे बदलावों से प्रभावित नहीं होगा, जो व्यवहार को पुन: क्रमबद्ध करने के परिणामस्वरूप होते हैं ताकि व्यवहार मेरे कार्यक्रम के नए संस्करणों के पुराने संस्करणों के अनुरूप होगा।
एकमात्र समाधान मैं अब तक के बारे में सोच कर लिया है इस तरह की कुछ मूल्य एप्सिलॉन उपयोग करने के लिए है:
if (value < epsilon) something_happens();
लेकिन क्योंकि परिणामों में छोटे बदलाव के समय के साथ जमा मैं एप्सिलॉन काफी बनाने की जरूरत है बड़े (अपेक्षाकृत बोलते हुए) यह सुनिश्चित करने के लिए कि विविधताएं किसी भिन्न चरण पर ट्रिगर होने पर कुछ_happens() नतीजे न हों। क्या कोई बेहतर तरीका है?
मैंने this excellent article को फ़्लोटिंग पॉइंट तुलना पर पढ़ा है, लेकिन मुझे नहीं लगता कि वर्णित तुलनात्मक तरीकों में से कोई भी इस स्थिति में मेरी मदद कर सकता है।
नोट: इसके बजाय पूर्णांक मानों का उपयोग करना एक विकल्प नहीं है।
संपादित तैरता के बजाय युगल उपयोग करने की संभावना बढ़ा दिया गया है। यह मेरी समस्या का समाधान नहीं करेगा क्योंकि भिन्नताएं अभी भी वहां होंगी, वे केवल एक छोटी परिमाण की होगी।
यदि छोटे बदलावों में आउटपुट में बड़े बदलाव आते हैं, तो क्या यह सिर्फ आपको नहीं बता रहा है कि आपके परिणामों की कम सटीकता है? (इसके अलावा: क्यों नहीं तैरना डबल?) –
सावधान रहें: 'printf ("%। 16f \ n ", f1); 'यह एक अप्रत्याशित साइड इफेक्ट है: यह आपकी फ्लोट को डबल महत्वपूर्ण गैर-महत्वपूर्ण अंकों में परिवर्तित कर देगा। मुझे लगता है कि एक फ्लोट, अधिकतम पर 7 अंकों की सटीकता। –
फ्लोटिंग पॉइंट मानों को समेटने का मानक तरीका यह है: उन्हें आदेश देने के लिए और कम से कम सबसे कम से कम इस कम से कम सटीकता को कम करें। डबल फ्लोट का भी उपयोग करें। –