經得起雷劈:關於double和int/long相互轉換失去精度計算錯誤的問題
阿新 • • 發佈:2019-01-04
http://blog.csdn.net/vonger/article/details/6656219
在用C/C++做運算時,型別轉換是很常見的,一般都直接用資料型別進行預設強制轉化,但是這樣其實是有很大問題的。
- #include <stdio.h>
- int main(int argc, char *argv[])
- {
- double x = 2.01;
- int y = x * 100;
- printf("y = %d\n", y);
- return 0;
- }
這個例子一眼看過去,很簡單嘛,應該是輸出201, 但是實際執行結果確是200...200和201的差距可是相當大了,足夠讓火箭墜毀動車被雷劈了 :)
所以,我們作為無證程式設計師,要寫出經得起雷劈的程式,這些想當然的BUG必須是要規避的。我採用的是double轉換int末位四捨五入的方法。
程式碼如下
- inlineint double2int(double in)
- {
- return in > 0 ? (in + 0.5) : (in - 0.5);
- }
這樣得到的就是正確的結果了。
- #include <stdio.h>
- int main(int argc, char *argv[])
- {
- double x = 2.01;
-
int y = double2int(x * 100);
- printf("y = %d\n", y);
- return 0;
- }
現在來分析根本原因:
由於浮點和整形的儲存方法是完全不同的,所以double y = 2.01在記憶體中實際是
FF FF FF FF FF 1F 69 40
經過IEEE的標準換算過來其實是2.00999999997, 這樣,乘以100後得到200.99999997,強制轉換整形的演算法是向下取整,這樣導致結果成了200