[英]C++ Numerical truncation error
抱歉,如果愚蠢但無法找到答案。
#include <iostream>
using namespace std;
int main()
{
double a(0);
double b(0.001);
cout << a - 0.0 << endl;
for (;a<1.0;a+=b);
cout << a - 1.0 << endl;
for (;a<10.0;a+=b);
cout << a - 10.0 << endl;
cout << a - 10.0-b << endl;
return 0;
}
輸出:
0
6.66134e-16
0.001
-1.03583e-13
嘗試使用MSVC9,MSVC10,Borland C ++ 2010進行編譯。所有這些都到達了大約1e-13的錯誤。 只有1000,10000增量才能產生如此顯着的誤差累積是否正常?
是的,這是正常的數字表示浮點錯誤。 它與硬件必須接近大多數浮點數的事實有關,而不是精確地存儲它們。 因此,您使用的編譯器無關緊要。
這就是為什么當使用浮點錯誤時你永遠不應該這樣做:
if( foo == 0.0 ){
//code here
}
而是做
bool checkFloat(float _input, float _compare, float _epsilon){
return ( _input + _epsilon > _compare ) && ( _input - _epsilon < _compare );
}
想一想。 每個操作都會引入輕微錯誤,但是下一個操作會使用稍有錯誤的結果 給定足夠的迭代次數,您將偏離真實結果。 如果你願意,可以用t0 = (t + y + e), t1 = (t0 + y +e)
的形式寫出你的表達式,並用epsilon計算出術語。 從他們的術語,你可以估計近似誤差。
還有第二個錯誤來源:在某種程度上,你將結合相對較小和相對較大的數字。 如果你記得機器精度的定義, 1 + e = 1
,在某些時候操作將失去重要的位。
希望這有助於以外行的方式澄清
這是浮點數的問題 - 它們是近似的,奇怪的事情發生在零(即出現奇怪的表示)。 因此,對於您認為理所當然的數字的一些操作必須更精細地處理。
當比較兩個數字時,你不能簡單地說a == b
因為一個可能是0
而另一個是-1.03583e-13
因為沿着浮點運算的精度損失應用於a
和b
。 您必須選擇任意容差,如下所示: fabs(a,b) < 1e-8
。
打印數字時,通常需要限制打印的位數。 如果你使用printf
,你可以說printf("%g\\n", a);
,它不會打印像-1.03583e-13
這樣的東西。 我不知道是否存在類似於%g
的iostream
模擬; 在那兒?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.