为什么D + 0.1 + 0.2 == 0.3?

时间:2011-07-29 14:03:59

标签: floating-point floating-accuracy d constantfolding

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


更新

感谢LukeH。这是描述there的浮点常量折叠的效果。

代码:

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

3 个答案:

答案 0 :(得分:52)

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


您似乎在假设OP,您的代码中的浮点不准确性是确定性的并且可预测错误(在某种程度上,您的方法与那些不喜欢的人的方法相反)了解浮点数。)

虽然(正如Ben所指出的)浮点不准确确定性的,但从代码的角度来看,如果你不是非常谨慎地考虑每一步中你的价值观发生了什么,情况并非如此。任何数量的因素都可能导致0.1 + 0.2 == 0.3成功,编译时优化成为一个,这些文字的调整值是另一个。

依赖既不成功也不失败;不依赖于浮点相等

答案 1 :(得分:47)

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

答案 2 :(得分:5)

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

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