开发者

C++ Numerical truncation error

开发者 https://www.devze.com 2022-12-29 17:30 出处:网络
sorry if dumb but could not find an answer. #include <iostream> using namespace std; int main() { double a(0);

sorry if dumb but could not find an answer.

#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 <&开发者_开发问答lt; endl;
return 0;
}

Output:

0

6.66134e-16

0.001

-1.03583e-13

Tried compiling it with MSVC9, MSVC10, Borland C++ 2010. All of them arrive in the end to the error of about 1e-13. Is it normal to have such a significant error accumulation over only a 1000, 10000 increments?


Yes, this is normal numeric representation floating point error. It has to do with the fact that the hardware must approximate most floating point numbers, rather than storing them exactly. Thus, the compiler you use should not matter.

What Every Computer Scientist Should Know About Floating-Point Arithmetic


This is why when using a floating point error you should never do:

if( foo == 0.0 ){
    //code here
}

and instead do

bool checkFloat(float _input, float _compare, float _epsilon){
    return ( _input + _epsilon > _compare ) && ( _input - _epsilon < _compare );
}


think about this. every operation introduces slight error, but next operation uses slightly faulty result. given enough iterations, you will deviate from true result. if you like, write your expressions in the form t0 = (t + y + e), t1 = (t0 + y +e) and figure out terms with epsilon. from their terms you can estimate approximate error.

there is also second source of error: at some point you are combining relatively small and relatively large numbers, towards the end. if you recall definition of machine precision, 1 + e = 1, at some point operations will be losing significant bits.

Hopefully this helps to clarify in laymen terms


This is the issue with floating point numbers—they're approximate, and weird things happen at zero (that is, weird representations appear). Because of this, some of the operations on numbers you take for granted have to be handled more delicately.

When comparing two numbers, you can't simply say a == b because one might be 0 and the other -1.03583e-13 due to the loss of precision along the floating point operations applied to get to a and b. You have to choose an arbitrary tolerance, like this: fabs(a,b) < 1e-8.

When printing a number, you often need to limit the number of digits printed. If you use printf, you can say printf("%g\n", a);, which won't print things like -1.03583e-13 . I don't know if there's an iostream analog to %g; is there?

0

精彩评论

暂无评论...
验证码 换一张
取 消