7

抱歉,如果愚蠢但找不到答案。

#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 次增量中累积如此显着的错误是否正常?

4

4 回答 4

13

是的,这是正常的数字表示浮点错误。这与硬件必须近似大多数浮点数,而不是精确存储它们有关。因此,您使用的编译器应该无关紧要。

每个计算机科学家都应该知道的关于浮点运算的知识

于 2010-05-07T01:24:46.340 回答
2

这就是为什么在使用浮点错误时你永远不应该这样做:

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

而是做

bool checkFloat(float _input, float _compare, float _epsilon){
    return ( _input + _epsilon > _compare ) && ( _input - _epsilon < _compare );
}
于 2010-05-07T01:40:29.080 回答
2

想想这个。每个操作都会引入轻微的错误,但下一个操作会使用稍微错误的结果。给定足够的迭代次数,您将偏离真实结果。如果你愿意,可以在表格中写下你的表达式,t0 = (t + y + e), t1 = (t0 + y +e)并用 epsilon 找出术语。根据他们的条款,您可以估计近似误差。

还有第二个错误来源:在某些时候,您将相对较小和相对较大的数字组合到最后。如果你回忆一下机器精度的定义1 + e = 1,在某些时候操作会丢失重要的位。

希望这有助于用外行的方式澄清

于 2010-05-07T01:55:43.000 回答
1

这就是浮点数的问题——它们是近似的,奇怪的事情发生在零处(也就是说,出现了奇怪的表示)。正因为如此,一些你认为理所当然的对数字的操作必须更细致地处理。

比较两个数字时,不能简单地说a == b是因为一个可能是0,另一个是-1.03583e-13由于应用于 geta和的浮点运算的精度损失b。您必须选择任意容差,如下所示fabs(a,b) < 1e-8

打印数字时,通常需要限制打印的位数。如果你使用printf,你可以说printf("%g\n", a);,它不会打印像-1.03583e-13. 我不知道是否有iostream类似的%g; 有没有?

于 2010-05-07T01:39:53.303 回答