0.1+0.2==0.3?


  剛剛在逛Stack的時候,看見有人在問Java下的一個浮點數運算的問題,這個問題我之前也碰到過,不過項目中遇見的比較少,就忘記了。想想還是做個筆記,記錄一下,以供后續溫習。

有趣的小例子

  先做一道算術題0.1+0.2=?,也許你想都不用想就回答等於0.3,那么在計算機中是如何表現的呢?測試如下:

var a = 0.1 + 0.2;
var b = 0.3;
Console.WriteLine(a);
Console.WriteLine(a == b);

輸出結果是:0.3和False,0.3!=0.3?且不說為什么,再測試一段:

float a = 0.7f;
float b = 0.6f;
Console.WriteLine(a - b);

輸出結果是:0.09999996,不等於0.1,我的機器抽風了?再試試: 

float a = 0.75f;
float b = 0.25f;
Console.WriteLine(a - b);

輸出結果是:0.5,居然又正常了,頓時對C#有了一股深深的怨念,這點小事兒你都辦不好,不過想想那些大神的能力肯定甩我幾十條街,不會犯這種低級錯誤,還是看看為什么吧。

分析

  究其根本,還是因為計算機采用二進制來表示十進制數據,C#中采用IEEE754標准來存儲浮點格式,單精度的浮點格式分為1位符號位、8位偏置指數位、23位小數位,通常,我們將十進制轉換為二進制需要進行如下操作:

  將浮點型數據分為整數部分和小數部分,整數部分除2取余,得到的商再除以2取余,直到商等於0為止,然后把得到余數反序排列,就得到了整數部分;小數部分用乘2法不斷將整數部分取出,知道小數中的部分為0或者達到精度時為止。以4.25為例:

  整數位:4

  4/2=2                  0

  2/2=1                  0

  1/2=0                  1

  將001反序得到100即整數位4

  小數位:0.25

  0.25*2=0.5          0

  0.5*2=1.0            1

  01即表示0.25

可是當小數位為0.6時,推算如下:

  0.6*2=1.2            1

  0.2*2=0.4            0

  0.4*2=0.8            0

  0.8*2=1.6            1

  0.6*2=1.2            1

  0.2*2=0.4            0

  0.4*2=0.8            0

  0.8*2=1.6            1

  ......

如此循環往復,很明顯23位是無法完全表述0.6這個小數的,這也就導致了上訴異常的產生。

  .NET中提供了decimal來解決這個問題,但decimal也是浮點數類型,只是精度更高,仍然有精度損失存在,所以,浮點數運算是一件非常危險的事情,還請慎重。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM