2014-09-06 7 views
11

यहाँ कोड है कि मुझे समझ में न का एक हिस्सा है:कास्ट प्रकार के आधार पर विभाजन का परिणाम अलग क्यों होता है?

byte b1 = (byte)(64/0.8f); // b1 is 79 
int b2 = (int)(64/0.8f); // b2 is 79 
float fl = (64/0.8f); // fl is 80 

क्यों एक के बाद बंद पहले दो गणना कर रहे हैं? मुझे यह ऑपरेशन कैसे करना चाहिए, तो यह तेज़ और सही है?

संपादित करें: मैं बाइट

+0

मैं अपने शीर्षक संपादित किया है। कृपया देखें, "[प्रश्नों में उनके शीर्षक में" टैग "शामिल होना चाहिए?] (Http://meta.stackexchange.com/questions/19190/)", जहां आम सहमति है "नहीं, उन्हें नहीं करना चाहिए"। –

+0

जॉन स्कीट द्वारा इस आलेख में आपके प्रश्न को शामिल करना चाहिए: http://csharpindepth.com/articles/general/floatingpoint.aspx – Warlock

उत्तर

6

संपादित करें: पूरी तरह से सही नहीं है, देखें: Why does a division result differ based on the cast type? (Followup)

गोलाई मुद्दा: बाइट/पूर्णांक में परिवर्तित करने के लिए, आप दशमलव स्थानों के कतरन हो रहे हैं।

लेकिन 64/0.8 कोई दशमलव स्थान नहीं होने चाहिए? गलत: फ़्लोटिंग पॉइंट नंबरों की प्रकृति के कारण, 0.8 एफ को स्मृति में बिल्कुल उसी तरह प्रदर्शित नहीं किया जा सकता है; यह 0.8f के करीब कुछ है (लेकिन वास्तव में नहीं) के रूप में संग्रहीत किया जाता है। Floating point inaccuracy examples या इसी तरह के धागे देखें। इस प्रकार, गणना का परिणाम 80.0f नहीं है, लेकिन 79.xxx जहां xxx 1 के करीब है लेकिन अभी भी बिल्कुल नहीं है।

आप दृश्य स्टूडियो में तत्काल विंडो में निम्न लिखकर इस की पुष्टि कर सकते हैं:

(64/0.8f) 
80.0 
(64/0.8f) - 80 
-0.0000011920929 
100 * 0.8f - 80 
0.0000011920929 

आप राउंडिंग का उपयोग करके इस का समाधान कर सकते हैं:

byte b1 = (byte)(64/0.8f + 0.5f); 
int b2 = (int)(64/0.8f + 0.5f); 
float fl = (64/0.8f); 
+1

80.0f को ठीक से प्रदर्शित किया जा सकता है। 0.8f, हालांकि, आप वास्तव में पहले स्थान पर 80.0f नहीं प्राप्त कर सकते हैं। – harold

+0

इसे पकड़ने के लिए धन्यवाद - मैंने तदनुसार अपना जवाब तय किया। – Matthias

+1

कृपया मेरा अनुवर्ती प्रश्न देखें: http://stackoverflow.com/questions/25703864/why-does-a-division-result-differ-based-on-the-cast-type-followup मुझे बाइनरी मिली (64/0.8 एफ) और पिछड़ा काम किया और यह वास्तव में बिल्कुल 80 के बराबर है। – ConditionRacer

3

में परिणाम की आवश्यकता होगी समस्या को समझने के लिए, आप चल बिन्दु प्रतिनिधित्व और संचालन की बुनियादी बातों को समझना होगा।

0.8f को फ़्लोटिंग पॉइंट नंबर का उपयोग करके स्मृति में बिल्कुल प्रतिनिधित्व नहीं किया जा सकता है।

गणित में, 64/0.8 के बराबर होती है 80 चल बिन्दु arithmetics में, 60/0.8 approximatively 80

के बराबर होती है जब आप एक पूर्णांक या एक बाइट के लिए एक नाव डाली, केवल संख्या के पूर्णांक हिस्सा है रखा। आपके मामले में, फ्लोटिंग पॉइंट डिवीजन का अपूर्ण परिणाम 80 से थोड़ा छोटा है इसलिए पूर्णांक उपज में रूपांतरण 79.

यदि आपको एक पूर्णांक परिणाम की आवश्यकता है, तो मैं आपको इसे कास्ट करने के बजाय परिणाम को गोल करने का सुझाव दूंगा ।

Convert.ToInt32(64/0.8f); 
5

मुझे डर है कि तेजी से और सही इस तरह के मामलों में अंतर पर कर रहे हैं रहा हूँ: एक तरह से यह करने के लिए निम्नलिखित समारोह, कि निकटतम पूर्णांक को गोलाई से एक पूर्णांक में बदलने का उपयोग करने के लिए है।

the underlying representation in our CPU architectures के कारण बाइनरी फ़्लोटिंग पॉइंट अंकगणित लगभग हमेशा छोटी त्रुटियां उत्पन्न करता है। तो आपकी प्रारंभिक अभिव्यक्ति में आपको वास्तव में गणितीय रूप से सही से थोड़ा सा मान मिलता है। यदि आप किसी विशेष गणितीय ऑपरेशन के परिणामस्वरूप पूर्णांक की अपेक्षा करते हैं और आपको इसके बहुत करीब कुछ मिलता है, तो आप सही गोल करने और छोटी त्रुटियों के लिए क्षतिपूर्ति करने के लिए Math.Round(Double, MidpointRounding) विधि का उपयोग कर सकते हैं (और सुनिश्चित करें कि आप the MidpointRounding strategy you expect चुनते हैं)।

बस एक प्रकार जैसे byte या int गोलाई नहीं करता है के लिए परिणाम कास्टिंग - यह केवल आंशिक भाग को काट देता है (यहां तक ​​कि 1.99999f1 हो जाएगा जब तुम सिर्फ इन प्रकार के लिए यह डाली)।

दशमलव फ़्लोटिंग पॉइंट अंकगणित धीमा और अधिक स्मृति गहन है, लेकिन इन त्रुटियों का कारण नहीं है। इसे करने के लिए, float अक्षरों (उदा। 64/0.8m) के बजाय decimal अक्षरों का उपयोग करें।

The rule of thumb है:

  • आप सटीक मात्रा के साथ काम कर रहे हैं, तो (आमतौर पर मानव निर्मित पैसे की तरह,), decimal का उपयोग करें।
  • यदि आप असीमित मात्रा से निपट रहे हैं (जैसे fractional भौतिक स्थिरांक या π जैसे तर्कहीन संख्या), double का उपयोग करें।
  • यदि आप अचूक मात्रा (ऊपर के रूप में) से निपट रहे हैं और कुछ सटीकता को गति के लिए आगे बलि किया जा सकता है (जैसे ग्राफिक्स के साथ काम करते समय), float का उपयोग करें।
संबंधित मुद्दे

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