2014-09-06 44 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/)」,其中的共識是「不,他們不應該」。 – 2014-09-06 18:24:47

+0

Jon Skeet的這篇文章應該涵蓋你的問題:http://csharpindepth.com/articles/general/floatingpoint.aspx – Warlock 2014-09-06 19:02:20

回答

6

編輯:不完全正確,請參閱:Why does a division result differ based on the cast type? (Followup)

四捨五入問題:通過轉換爲字節/ INT,你剪輯的小數位。

64/0.8不應該導致任何小數位?錯誤:由於浮點數的性質,0.8f不能完全像內存中那樣表示;它被存儲爲接近0.8f(但不完全)。見Floating point inaccuracy examples或類似的線程。因此,計算結果不是80.0f,而是79.xxx,其中xxx接近於1,但仍不完全爲1。

您可以通過鍵入以下到即時窗口在Visual Studio中驗證這一點:

(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 2014-09-06 18:30:33

+0

感謝您的追捕 - 我相應地解決了我的問題。 – Matthias 2014-09-06 18:36:13

+1

請查看我的後續問題:http://stackoverflow.com/questions/25703864/why-does-a-division-result-differ-based-on-the-cast-type-followup我得到了二進制(64/0.8f)並反向工作,它確實等於80。 – ConditionRacer 2014-09-06 19:39:26

3

結果要理解這個問題,你需要了解浮點表示和操作的基本知識。

0.8f不能在內存中使用浮點數精確表示。

在數學中,64/0.8等於80 在浮點算術,60/0.8等於近似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)。

簡單鑄造結果的類型,如byteint不做四捨五入 - 它只是切斷小數部分(甚至1.99999f將成爲1當你只是將它轉換爲這些類型)。

十進制浮點運算速度較慢且內存密集程度較高,但不會導致這些錯誤。要執行此操作,請使用文字decimal而不是float(例如64/0.8m)。

The rule of thumb是:

  • 如果你正在處理的確切數量(通常是人造的,如金錢),使用decimal
  • 如果您處理的是不精確數量(如分數物理常數或像π這樣的無理數),請使用double
  • 如果您處理的是不精確的數量(如上所述),並且速度可能會進一步犧牲一些精度(例如使用圖形時),請使用float