1. 程式人生 > >經得起雷劈:關於double和int/long相互轉換失去精度計算錯誤的問題

經得起雷劈:關於double和int/long相互轉換失去精度計算錯誤的問題

http://blog.csdn.net/vonger/article/details/6656219

在用C/C++做運算時,型別轉換是很常見的,一般都直接用資料型別進行預設強制轉化,但是這樣其實是有很大問題的。

  1. #include <stdio.h>
  2. int main(int argc, char *argv[])  
  3. {  
  4.     double x = 2.01;  
  5.     int y = x * 100;  
  6.     printf("y = %d\n", y);  
  7.     return 0;  
  8. }  

這個例子一眼看過去,很簡單嘛,應該是輸出201, 但是實際執行結果確是200...200和201的差距可是相當大了,足夠讓火箭墜毀動車被雷劈了 :)

所以,我們作為無證程式設計師,要寫出經得起雷劈的程式,這些想當然的BUG必須是要規避的。我採用的是double轉換int末位四捨五入的方法。
程式碼如下

  1. inlineint double2int(double in)  
  2. {  
  3.     return in > 0 ? (in + 0.5) : (in - 0.5);  
  4. }  


這樣得到的就是正確的結果了。


  1. #include <stdio.h>
  2. int main(int argc, char *argv[])  
  3. {  
  4.     double x = 2.01;  
  5.     int y = double2int(x * 100);  
  6.     printf("y = %d\n", y);  
  7.     return 0;  
  8. }  

現在來分析根本原因:
由於浮點和整形的儲存方法是完全不同的,所以double y = 2.01在記憶體中實際是
FF FF FF FF FF 1F 69 40
經過IEEE的標準換算過來其實是2.00999999997, 這樣,乘以100後得到200.99999997,強制轉換整形的演算法是向下取整,這樣導致結果成了200