#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增量才能产生如此显着的误差累积是否正常?
答案 0 :(得分:13)
是的,这是正常的数字表示浮点错误。它与硬件必须接近大多数浮点数的事实有关,而不是精确地存储它们。因此,您使用的编译器无关紧要。
What Every Computer Scientist Should Know About Floating-Point Arithmetic
答案 1 :(得分:2)
这就是为什么当使用浮点错误时你永远不应该这样做:
if( foo == 0.0 ){
//code here
}
而是做
bool checkFloat(float _input, float _compare, float _epsilon){
return ( _input + _epsilon > _compare ) && ( _input - _epsilon < _compare );
}
答案 2 :(得分:2)
t0 = (t + y + e), t1 = (t0 + y +e)
形式写下你的表达式,并用epsilon计算出术语。从他们的术语,你可以估计出近似误差。
还有第二个错误来源:在某些时候,你要将相对较小和相对较大的数字组合在一起。如果你记得机器精度的定义1 + e = 1
,那么在某些时候操作将失去重要的位。
希望这有助于以非专业术语澄清
答案 3 :(得分:1)
这是浮点数的问题 - 它们是近似的,奇怪的事情发生在零(即出现奇怪的表示)。因此,对你认为理所当然的数字的一些操作必须更精细地处理。
比较两个数字时,您不能简单地说a == b
,因为一个可能是0
而另一个-1.03583e-13
是由于沿着应用于浮点运算的精度损失到a
和b
。您必须选择任意容差,如下所示:fabs(a,b) < 1e-8
。
打印数字时,通常需要限制打印的位数。如果您使用printf
,则可以说printf("%g\n", a);
,这不会打印-1.03583e-13
之类的内容。我不知道iostream
类似于%g
;在那里?