Decimal與double類型誤差

來源:互聯網
上載者:User

 int a = (int)(19.9 *100);   //19.9預設是double類型
 int b = (int)(19.9M *100 ); //將19.9轉換成decimal類型

 Console.WriteLine(a);  //輸出:1989

 Console.WriteLine(b);  //輸出:1990

 

不用說.NET,C#,就是用Java來幹估計也是這個結果,這個結果具有必然性.
19.9 作為 Double 類型表示,二進位形式是:
1 00000000110 011111001100110011001100110011001100110011001100110
(注意中間的兩個空格,如果你不知道啥意思,就去查查double的記憶體表示形式吧)
但是19.9 * 100 由於是二進位運算的結果是
1 00000010011 111000101111111111111111111111111111111111111111111
由於後面有n個11111所以我猜測可能發生了溢出被電腦捨去了.
於是這個數字比 1990少那麼一點點(可能是 1989.99999999...)
但是你的取整操作卻直接截斷了後面的數字,於是成了1989
至於你說9.9 29.9為什麼不那樣,那就是可能沒有發生溢出了(不要以10進位的思維來猜測二進位)
別的語言你只能通過保留更高的精度並且四捨五入來實現,而C#為了支援金融運算,獨家引入變態的Decimal類型,於是你的問題現在可以通過decimal解決了(decimal的精度非常高,大約有好幾十層樓那麼高吧...夠用了)
二進位無法精確表示浮點數,小數部分一般都是用近似值來標示的。所以19.9*100的二進位標示會有那麼多的11111111。而(int)(19.999999999)結果是直接截斷小數點後面的結果,所以1989.999999也就是1989了。但是decimal為什麼能正確呢,因為它根本就不存在真正的小數儲存進位,所有的數都在小數點的右邊。那它又是如何儲存小數的呢,答案就是比例因素。當然還有符號位。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.