2011-10-28 7 views
5

मैं फ़ंक्शन ऑप्टिमाइज़ेशन रूटीन (नेल्डर-मीड एल्गोरिदम का एक संस्करण) पर काम कर रहा हूं जो बहुत विशिष्ट स्थितियों में अभिसरण करने में विफल रहता है।इस सिंगल-परिशुद्धता ऑपरेशन का परिणाम कैसे गोल किया गया है? [या यह बिट 1 और 0 क्यों नहीं है?]

मैं पता चला है कि एक float चर, चलो यह a कॉल, a और अन्य चर का b कि एक सा ही से यह से अलग है के बीच मतलब सौंपा जा रहा है।

दरअसल, प्रत्येक चरों के मान इस प्रकार हैं:

float a = 25.9735966f; // 41CFC9ED 
float b = 25.9735947f; // 41CFC9EC 

और अब मैं a को a और b के बीच मतलब आवंटित करने के लिए कोशिश कर रहा हूँ:

a = 0.5 * (a+b); 

जब मैं लिखने एक परीक्षण कार्यक्रम में यह कोड, मुझे परिणाम मिलना है, अर्थात् 25.9735947। लेकिन मेरे मूल पुस्तकालय कोड के डीबगर में मैं देखता हूं कि 25.9735966 अवशेषों का मान है। मुझे यकीन है कि मेरे पास दोनों कार्यक्रमों पर एक ही कंपाइलर झंडे हैं। क्या कोई कारण है कि यह सिंगल-परिशुद्धता गणना अलग-अलग परिणाम क्यों देगी?

अद्यतन

रूप @PascalCuoq का अनुरोध किया, यहाँ मैं क्या सोचता प्रश्न में लाइन के लिए विधानसभा है। रेखा कुछ अन्य चीजें कर रही है हालांकि मुझे यकीन नहीं है कि गुणा कहाँ होता है।

.loc 1 53 0 discriminator 2 
movl -60(%rbp), %eax 
cltq 
salq $3, %rax 
addq -88(%rbp), %rax 
movq (%rax), %rax 
movl -44(%rbp), %edx 
movslq %edx, %rdx 
salq $2, %rdx 
leaq (%rax,%rdx), %rcx 
movl -44(%rbp), %eax 
cltq 
salq $2, %rax 
addq -72(%rbp), %rax 
movl -60(%rbp), %edx 
movslq %edx, %rdx 
salq $3, %rdx 
addq -88(%rbp), %rdx 
movq (%rdx), %rdx 
movl -44(%rbp), %esi 
movslq %esi, %rsi 
salq $2, %rsi 
addq %rsi, %rdx 
movss (%rdx), %xmm1 
movl -52(%rbp), %edx 
movslq %edx, %rdx 
salq $3, %rdx 
addq -88(%rbp), %rdx 
movq (%rdx), %rdx 
movl -44(%rbp), %esi 
movslq %esi, %rsi 
salq $2, %rsi 
addq %rsi, %rdx 
movss (%rdx), %xmm0 
addss %xmm1, %xmm0 
movss .LC6(%rip), %xmm1 
mulss %xmm1, %xmm0 
movss %xmm0, (%rax) 
movl (%rax), %eax 
movl %eax, (%rcx) 

स्पष्टीकरण

मेरे कोड न्यूमेरिकल व्यंजनों से Nelder-मीड कोड का एक ripoff संस्करण है। p[i][j] == 25.9735966f और p[ilo][j] == 25.9735947f

p[i][j]=psum[j]=0.5*(p[i][j]+p[ilo][j]); 

इस पंक्ति में,: हमलावर लाइन इस एक है। p[i][j] में परिणामस्वरूप मान 25.9735966f है।

+0

मेरे पास अभी तक कोई स्पष्टीकरण नहीं है, लेकिन 25।9735 9 47 निकटतम ** यहां तक ​​कि ** परिणाम के लिए सही गोल है, क्योंकि मुझे लगता है कि आपको मुझे बताने की आवश्यकता नहीं है। –

+1

मूल लाइब्रेरी कोड से 'ए = 0.5 * (ए + बी);' के लिए असेंबली देखने का कोई मौका? उसमें कोई अन्य लाइब्रेरी लिंक नहीं हो सकती है जो राउंडिंग मोड को "मददगार" सेट कर सकती है? –

+0

जब आप "डीबगर में" कहते हैं, तो क्या आपका मतलब है कि जब आप डीबगर का उपयोग करके मानों का निरीक्षण करते हैं, या क्या आपका मतलब है कि इस लाइब्रेरी के डीबगर संस्करण का उपयोग करते समय, अन्यथा सामान्य रूप से चलने पर, अलग-अलग परिणाम उत्पन्न होते हैं? –

उत्तर

2

मैं आईईईई 754-19 85 के प्रासंगिक भाग को फिर से पढ़ता हूं, यह मानते हुए कि आपका फ़्लोटिंग-पॉइंट कार्यान्वयन उस मानक के अनुरूप है। केवल एक चीज जो दिमाग में आती है वह यह है कि आपके दो वातावरण में विभिन्न गोल करने वाले तरीके हैं।

  • निकटतम करने के लिए गोल, और समान दूरी के मामले में:: ये संभावनाएं हैं शून्य =>25.9735947f
  • दौर की ओर +INF =>25.9735966f
  • दौर की ओर 0 =>25.9735947f को कम से कम महत्वपूर्ण बिट सेट
  • -INF की ओर दौर =>25.9735947f

तो केवल संभावना है कि है आपके डीबगिंग वातावरण में गोलाकार मोड + INF की ओर है। मेरे लिए, कोई अन्य व्यावहारिक स्पष्टीकरण नहीं है।

+0

की याद दिलाता है 'टूटा-गणित' जैसी टूटी चीजों के बारे में क्या? या क्या होगा यदि मध्यवर्ती परिणाम की गणना उच्च/निम्न परिशुद्धता पर की जा रही है? –

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