C ++使用双重比较的奇怪行为

时间:2014-03-03 16:45:45

标签: c++ double

我正在为我的应用程序开发一个单元测试,但是我遇到了一个我不明白的奇怪问题。

代码是:

double res = BytesTool::convertSize(1, BytesTool::Byte, BytesTool::KiloByte);
double tmp = pow((double)1000, -1);
QVERIFY(res == tmp);

我正在使用gcc(主机64位)从Linux机器(主机64位)编译Linux 64位,并使用Linux的mingw32编译器对Windows 32位进行交叉编译。

该程序在调试和发布模式下使用Linux编译正常工作(断言成功)。 对于Windows版本,它在调试版本中工作正常,但不适用于发行版本;断言失败了。

奇怪的是,如果我插入一个跟踪,测试在Windows中可以运行:

double res = BytesTool::convertSize(1, BytesTool::Byte, BytesTool::KiloByte);
printf("test");
double tmp = pow((double)1000, -1);
QVERIFY(res == tmp); // Is TRUE when printf("test") is present, FALSE otherwise

我迷路了,我真的不明白发生了什么。为什么printf能够使其发挥作用?

感谢您的帮助。

2 个答案:

答案 0 :(得分:6)

printf将使其工作,因为浮点数将从内部FPU 80位表示(假设x86“旧式”数学运算)转换为保存在double中的64位。

这样做的原因是当你调用另一个函数时,寄存器值必须被移动到堆栈(再次,假设x86旧式FPU调用约定),这将导致它被四舍五入到64位精度。 / p>

您的其他编译很可能有效,因为它们使用SSE2 + math,它具有本机64位浮点类型。

==测试浮点数相同,这对于浮点数几乎不是正确的。

在这种情况下,它不是因为内部CPU表示与存储在double中的表示不同。

比较浮点数时,请务必检查它们是否彼此足够接近而不是相等。

#include <math.h>

QVERIFY( fabs(res-tmp) < DBL_EPSILON )

答案 1 :(得分:-1)

它将会消失一点点。 Double的工作原理与浮点相同,这很好地解释了https://www.youtube.com/watch?v=PZRI1IfStY0