75
assert(0.1 + 0.2 != 0.3); // shall be true

是我最喜欢的检查语言是否使用本机浮点运算。

C++

#include <cstdio>

int main()
{
   printf("%d\n", (0.1 + 0.2 != 0.3));
   return 0;
}

输出:

1

http://ideone.com/ErBMd

Python

print(0.1 + 0.2 != 0.3)

输出:

True

http://ideone.com/TuKsd

其他示例

为什么这对 D 不成立?据了解,D 使用本机浮点数。这是一个错误吗?他们是否使用某些特定的数字表示?还有什么?相当混乱。

D

import std.stdio;

void main()
{
   writeln(0.1 + 0.2 != 0.3);
}

输出:

false

http://ideone.com/mX6zF


更新

感谢卢克H。这是那里描述的浮点常量折叠的效果。

代码:

import std.stdio;

void main()
{
   writeln(0.1 + 0.2 != 0.3); // constant folding is done in real precision

   auto a = 0.1;
   auto b = 0.2;
   writeln(a + b != 0.3);     // standard calculation in double precision
}

输出:

false
true

http://ideone.com/z6ZLk

4

3 回答 3

53

(弗林的答案是正确的答案。这个更普遍地解决了这个问题。)


OP,您似乎在假设代码中的浮点不准确性是确定性的并且可以预见是错误的(在某种程度上,您的方法与还不了解浮点的人的方法截然相反)。

尽管(正如 Ben 指出的)浮点不准确性确定性的,但从您的代码的角度来看,如果您在每一步都没有仔细考虑您的值会发生什么,那么情况就不会如此。任何数量的因素都可能导致0.1 + 0.2 == 0.3成功,编译时优化是一个,这些文字的调整值是另一个。

在这里既不依赖成功也不依赖失败;无论哪种方式都不要依赖浮点相等。

于 2011-07-29T14:21:19.667 回答
47

它可能被优化为 (0.3 != 0.3)。这显然是错误的。检查优化设置,确保它们已关闭,然后重试。

于 2011-07-29T14:06:49.837 回答
5

根据我对D 语言规范的解释,x86 上的浮点运算将在内部使用 80 位精度,而不仅仅是 64 位。

然而,人们必须检查这足以解释您观察到的结果。

于 2011-07-29T14:14:44.017 回答