[英]Best practices for floating-point arithmetics
我正在對小數點輸入執行加法和減法,精確到小數點后第二位。 我試圖通過乘以100將它們轉換為整數來提高准確度,但卻達到了相反的效果。
請考慮以下代碼和輸出:
double d = 2.01;
int a = (int) (d * 100.0);
cout << a << endl;
輸出是:
200
一勞永逸,關於浮點算術的一些最佳實踐是什么? 首先使用上面代碼的一些變體將double
轉換為int
,然后將其轉換回來是否可行?
如果將d*100.0
的結果打印到(比方說)20位小數,問題將很快變得明顯:
200.99999999999997
由於那(小得多)小於201,當你轉換為int
時它會被截斷為200。
顯而易見的解決方法是強制四舍五入。 至少如果你的輸入都是正數,那么就像在結果中加0.5一樣簡單:
int a = (int)(d*100.0 + 0.5);
如果你可以指望你的編譯器支持它,那么使用標准庫的round
會更容易:
long a = lround(d*100.0);
這適用於正數和負數。
使用標准數學庫的舍入函數。 在C ++中,這意味着您必須#include <cmath>
並使用-lm
編譯。
然后,為您的例子:
double d = 2.01;
long x = lround(d*100);
cout << x << endl; // prints 201, for sure.
這將與“添加.5”技巧相同,但它對正數和負數都能正常工作。
閱讀本文並達成啟示:
浮點算術被許多人認為是一個深奧的主題。 這是相當令人驚訝的,因為浮點在計算機系統中無處不在。 幾乎每種語言都有浮點數據類型; 從PC到超級計算機的計算機都有浮點加速器; 大多數編譯器都會被要求不時編譯浮點算法; 幾乎每個操作系統都必須響應溢出等浮點異常。 本文提供了一個關於浮點的方面的教程,這些方面對計算機系統的設計者有直接影響。 它首先介紹浮點表示和舍入誤差,繼續討論IEEE浮點標准,最后總結了許多計算機構建器如何更好地支持浮點的例子。
為了得到明確的路由,我會使用floor()和ceil()。
那么,對於以下代碼,
(int)floor( 2.01*100.)
我明白了:
200
但對於:
(int)ceil(2.01*100.)
我明白了:
201
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.