C# double類型精度丟失問題


  我們先看一段代碼,可以在控制台程序中執行看看結果  

    {
        double d = 500;
        double d1 = 233.84;
        double d2 = d - d1;
        //d2=266.15999999999997
    }
    {
        double d = 0.4;
        double d1 = d + d + d;
        //d1=1.2000000000000002
        double d2 = d * 3;
        //d2=1.2000000000000002
    }
    {
        double d = 1.2;
        double d1 = d / 0.4;
        //d1=2.9999999999999996
    }

  看到結果,你可能驚訝或者不驚訝,認為計算機計算出現這種精度問題很正常,但是當你做判斷時,發現1.2!=0.4*3或者3!=1.2/0.4,你就會懵逼了  

    bool b1 = 1.2 == 0.4 * 3;//false
    bool b2 = 3 == 1.2 / 0.4;//false

  更有甚者,將計算出來的double類型直接保存在數據庫,那保存的也是上面那一堆的小數,后來者看到這個也是奔潰的!

  

  更大的影響是在做金額運算時,我們一般都是精確到分,但是有時會計會發現自己計算出來的數據和我們系統中的對不上,我們的第一感覺也是精度問題,往往會做一個四舍五入,向上取值,向下取值等等操作,那么更大的問題來了,比如向下取值,你會發現1.2/0.4向下取整等於2!  

    double b = Math.Floor(1.2 / 0.4);//b=2

  心中一萬只草泥馬奔騰而過!

  float、double和decimal

  float、double和decimal是C#中表示浮點數的類型

類型 名稱 bit 有效數字 數值范圍 是否基礎類型
float 單精度浮點數 32 7 ±1.5×10E−45 ~ ±3.4×10E38
double 雙精度浮點數 64 15/16 ±5.0×10E−324 ~ ±1.7×10E308
decimal 高精度浮點數 128 28 ±1.0×10E−28 ~ ±7.9×10E28

  float和double都是基礎類型,區別就是表示的數值范圍和精度不一樣,而decimal是C#作為補充加上來的一個類型,不是基礎類型,它擁有更高的精度,但是表示的數值范圍卻小多了,而且計算速度相對來說要慢一些,但是也足夠一般的業務需求了,比如上面的例子,如果把double都換成decimal就不會出現問題了。

  float、double和decimal都有精度丟失問題,只不過他們在丟失時的精度條件不一樣,而且精度丟失了還不報異常。

  個人建議

  1、在項目中盡可能的使用decimal,雖然decimal也會出現精度丟失問題,但是一般業務需求是沒問題的。

  2、當方法返回浮點類型時,或者返回的實體包含有浮點類型,那么在返回時一定要考慮要不要處理精度問題。

  3、在對外輸出或者存儲時,如保存到數據庫,一定要根據自己的需求做個精度處理。

  4、當基礎類型在不同類型之間轉換時,盡可能的使用Convert類中的方法,少用強制轉換。 

  5、盡量避免使用浮點數做比較,如果愣是比較,可以先做精度處理或者先轉換成整型再比較。

 


免責聲明!

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



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