我正在玩下面的代码
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
int main() {
double speed = 60.0;
double distance;
int a, b, c;
scanf("%lf %d %d %d", &distance, &a, &b, &c);
cout << distance << " " << a << " " << b << " " << c << endl;
cout << (fmod((distance*3600)/speed, (a + b + c))) << endl;
return 0;
}
并注意到,对于以下输入
15.1 1 1 1
它在我的机器上产生了这个(不正确的?)结果
15.1 1 1 1
3
但似乎在ideone(http://ideone.com/mwMalv)
上产生了这个结果15.1 1 1 1
0
我意识到“0.1”(在“15”中)不能准确地表示为双重
http://www.exploringbinary.com/why-0-point-1-does-not-exist-in-floating-point/
但是其他使用gcc 4.8.2运行此代码的人也获得了在ideone上生成的内容。
我正在使用Ubuntu 14.04.2 LTS Desktop (32-bit)
在VMware 6.0.5 build-2443746
上运行gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
。
是什么给出的?为什么fmod
在我的机器上的行为与在其他机器上的行为不同(假设编译器相同)?
答案 0 :(得分:1)
您的计算结果大约为fmod(906, 3)
。但是,906
可能是905.9999999999998532
或其他内容,因为错误的值无法准确表示。
fmod
后者3
的结果会给2.999999999999999998532
,当舍入到默认精度3
时,6
会显示为<< setprecision(30)
。< / p>
要详细了解详情,请在cout
声明中906
。
检查每种情况下生成的装配输出也可能很有启发性。也许编译器正在做不同的事情;或者他们也在做同样的事情而且FPU是不同的。
例如,double
的结果甚至可能比double
的精度更高。在转到fmod
之前更改代码以将其存储在{{1}}中可能会也可能不会产生影响。