簡體   English   中英

C ++數字截斷錯誤

[英]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因為沿着浮點運算的精度損失應用於ab 您必須選擇任意容差,如下所示: fabs(a,b) < 1e-8

打印數字時,通常需要限制打印的位數。 如果你使用printf ,你可以說printf("%g\\n", a); ,它不會打印像-1.03583e-13這樣的東西。 我不知道是否存在類似於%giostream模擬; 在那兒?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM