2012-12-19 12 views
17

बयानडबल रूपांतरण में फ़्लोट - यूनिट परीक्षण में सर्वश्रेष्ठ दावा?

float f = 7.1f; 
double d = f; 

क्या हम घ के बारे में एक इकाई परीक्षण में जोर कर सकते हैं को देखते हुए?


उदाहरण के लिए यह काम नहीं करता:

Console.WriteLine(d == 7.1d); // false 
Console.WriteLine(d < 7.1d + float.Epsilon); // true by luck 
Console.WriteLine(d > 7.1d - float.Epsilon); // false (less luck) 

सबसे अच्छा तरीका है मैं अब तक पाया मूल्य वापस कन्वर्ट करने के लिए है:

float f2 = (float)d; 
Console.WriteLine(f2 == f); // true 

कौन सा जानवर के रूप में ही किया जाएगा

Console.WriteLine(d == 7.1f); // 7.1f implicitly converted to double as above 

यह प्रश्न सामान्य रूप से डबल और फ्लोट परिशुद्धता के बारे में नहीं है, लेकिन वास्तव में व्यावहारिक प्रश्न के बारे में केवल एक इकाई परीक्षण डी की सीमाओं का सबसे अच्छा वर्णन कैसे कर सकता है। मेरे मामले में, डी एक रूपांतरण का परिणाम है जो हल्के वजन कोड उत्पादन द्वारा उत्पन्न कोड में होता है। इस कोड पीढ़ी का परीक्षण करते समय, मुझे इस समारोह के नतीजे के बारे में दावा करना होगा और अंततः उपरोक्त सरल प्रश्न पर उबाल लें।

+0

आप किस इकाई परीक्षण ढांचे का उपयोग कर रहे हैं? हो सकता है कि आप जरूरी शर्त के खिलाफ ज़ोर देना न करें उदा। 'Assert.IsTrue (हालत)', आप उदाहरण का उपयोग करने में सक्षम हो सकता है 'Assert.AreEqual (value1, value2) 'जो संख्यात्मक प्रारूपों के बीच समानता को संभाल सकता है। – StuperUser

+0

मुझे अभी भी यकीन नहीं है कि आप यहां परीक्षण करने का प्रयास कर रहे हैं। एक डबल की एक फ्लोट की तुलना में अधिक सटीकता होती है और इस तरह वे शायद ही कभी एक दूसरे के बराबर "बराबर" होंगे। – CodeCaster

+0

यदि आप फ्लोट को प्रारंभ करने के लिए निरंतर उपयोग में अंतिम एफ को छोड़ देते हैं, तो यह और भी बदतर हो सकता है, यहां एक तैयार उदाहरण देखें http://stackoverflow.com/questions/13276862/cc-notation-of-double-floating-point -वृत्त/13279512 # 13279512 –

उत्तर

4

आपका "सबसे अच्छा तरीका" यह कह रहा है कि आपका जेनरेट कोड float त्रुटि के मार्जिन, 7.1 के भीतर कुछ देता है। यह हो सकता है कि आप जो जांचना चाहते हैं, उस स्थिति में, आगे बढ़ें।

दूसरी ओर, यदि आप अपने उत्पन्न कोड रिटर्न पर जोर करना चाह सकते हैं विशेष रूप से एक double को 7.1f कास्टिंग का परिणाम है, इस स्थिति में आप कर सकता है:

Console.WriteLine(d == (double)f); 

यह और अधिक कठोर है - आपका परीक्षण दावा करता है कि d एक छोटी सी सीमा के भीतर है, जबकि उपरोक्त परीक्षण का दावा है कि d एक विशिष्ट मान है।

यह वास्तव में इस बात पर निर्भर करता है कि आप d का उपयोग किस प्रकार करेंगे। यदि यह एक ऐसा मामला है जहां चीजें गलत हो जाएंगी, तो यह सही मूल्य नहीं है, तो सटीक मान का परीक्षण करें, लेकिन यदि यह मान के float के भीतर होना ठीक है, तो float के विरुद्ध जांचें।

+0

राउलिंग, यह मेरे लिए है। मैं उम्मीद करता हूं कि मेरा कोड 7.1f को दोहराएगा, इसलिए मेरा दावा अब डी। शॉल्ड() हो। ((डबल) 7.1 एफ); जो मेरी अपेक्षाओं को सबसे स्पष्ट बनाता है। आपके इनपुट के लिए thx। Ibm से संकेत के लिए – citykid

1

दो नाव बिंदु ibm sugests महत्व देता abs(a/b - 1) < epsilon

एक msnd कहा गया है कि Epsilon संपत्ति छोटी से छोटी सकारात्मक मूल्य है कि संख्यात्मक संचालन या तुलना में महत्वपूर्ण है जब उदाहरण का मान शून्य है दर्शाता है परीक्षण करने के लिए तुलना करने के लिए।

तो वास्तव में आप

Math.Abs(d/(double)f) - 1) < float.Epsilon) 
+0

thx: यदि आप अंतर्निहित माप के पैमाने को नहीं जानते हैं, तो "abs (a/b - 1) citykid

+0

+1। हां, संभवतः बड़ी संख्या में ईपीएसलॉन जोड़ने का कोई मतलब नहीं है। इसका कोई असर नहीं होगा। यह केवल निश्चित बिंदु संख्याओं के लिए काम करेगा। –

+0

आपके द्वारा इंगित दस्तावेज़ आईबीएम द्वारा प्रकाशित किया गया है, लेकिन इसे आईबीएम के अलावा किसी व्यक्ति और निगम द्वारा लिखित रूप में पहचाना जाता है। इसलिए यह स्पष्ट नहीं है कि आईबीएम उस सुझाव को बना रहा है, अब एक पुस्तक प्रकाशक लेखक द्वारा प्रकाशित लेखकों के साथ सहमत है। और इस पर आधारित इस बेवकूफ अभ्यास को बढ़ावा देने के आईबीएम पर आरोप लगाने के लिए पूरी तरह से उचित नहीं है। –

1

(float) d == f जांच होनी चाहिए।

एक और उत्तर d == (double) f का सुझाव दिया गया है, लेकिन यह एक बेकार परीक्षण है क्योंकि (double) f उसी रूपांतरण को करता है जो d = f स्पष्ट रूप से निष्पादित करता है। तो इस धारणा का परीक्षण करने वाली एकमात्र चीज यह है कि कार्यान्वयन का कुछ पहलू टूट गया है (उदा।, कंपाइलर ने रूपांतरणों में से एक को गलत तरीके से कार्यान्वित किया और दूसरी तरफ से अलग किया), कुछ बाहरी तंत्र ने d या f असाइनमेंट और दावे के बीच बदल दिया, या स्रोत कोड टूटा गया ताकि d न तो double और न ही float और न ही किसी प्रकार का जो f के मान को पकड़ सकता है या असाइनमेंट d = f निष्पादित नहीं किया गया था।

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

इसके बजाय, हम बड़े प्रारूप से वापस संकुचित प्रारूप में परिवर्तित करते हैं। यदि df से अलग है, तो इस रूपांतरण में त्रुटि का पता लगाने का मौका है। उदाहरण के लिए, मान लें कि f में 0x1p-1000 है, लेकिन, किसी कारण से, यह d के प्रारूप में प्रतिनिधित्व योग्य नहीं है, इसलिए यह शून्य पर गोल किया गया था। फिर (float) d == f(float) 0 == 0x1p-1000 पर मूल्यांकन करता है, फिर 0 == 0x1p-1000 पर, फिर false पर। इसके अतिरिक्त, यह परीक्षण अन्य सुझावों के समान त्रुटियों का पता लगा सकता है: एक टूटा कार्यान्वयन, d या f का परिवर्तन, गलत प्रकार का d, और d = f का एक गुम असाइनमेंट।

इसके अलावा, आप यहां किसी दावे के साथ किस त्रुटि का पता लगाने की कोशिश कर रहे हैं?

+0

यह ध्यान देने योग्य है कि 'फ्लोट' से' दशमलव तक 'या 'डबल' से' दशमलव 'तक रूपांतरण हानिकारक हो सकता है * यहां तक ​​कि उन मानों के लिए भी जो दोनों प्रारूपों में सटीक रूप से प्रदर्शित होते हैं *। उदाहरण के लिए, '16777215f' से' दशमलव तक 'को परिवर्तित करने से 16777220 का मूल्य मिलता है, भले ही' फ्लोट 'मान 16,777,215 मान का प्रतिनिधित्व करता है, और' दशमलव 'भी उस मान को पकड़ सकता है। – supercat

+0

@supercat: "... प्रत्येक सामान्य कार्यान्वयन में, कनवर्ट करना ... एक ही रेडिक्स के व्यापक परिशुद्धता ** में ** कोई त्रुटि नहीं है ..."। –

+0

यह सच है कि प्रत्येक 'फ्लोट' मान को 'दशमलव 'में * प्रतिनिधित्व करने योग्य * होने की उम्मीद नहीं कर सकता है, बशर्ते कि वे विभिन्न रेडिक्स का उपयोग करें, और निश्चित रूप से किसी ऐसे रूपांतरण में सटीक होने की अपेक्षा नहीं कर सकता जहां गंतव्य प्रारूप का कोई प्रतिनिधित्व नहीं है प्रश्न में मूल्य के लिए। मेरा इरादा आपसे विरोधाभास नहीं करना था, बल्कि यह बताने के लिए कि यदि रेडिक्स अलग-अलग हैं, तो पुराने और नए स्वरूपों में सटीक रूप से प्रतिनिधित्व करने वाले मूल्य भी अजीब रूप से परिवर्तित हो सकते हैं (शायद 16777215f से 16777220 मीटर का गोलाकार दस्तावेज है, लेकिन कम से कम यह कहना अजीब लगता है)। – supercat

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