IEEE 754: Javascript vs C

IEEE 754: Javascript vs C

本文关键字:vs Javascript IEEE      更新时间:2023-09-26

据我所知,著名的

 (0.1 + 0.2) !== 0.3

gotcha实际上并不是Javascript的错。这就是IEEE 754的工作方式。类似的输出发生在Python中,它也遵循IEEE 754规则。

那么为什么这个特定的例子有时会在 C 中按预期工作。如果我做一个直接比较

printf("%d'n", (0.1+0.2) == 0.3);

我得到(un?预期的输出0,但是如果我将值放入变量中或将它们打印出来,我会得到正确舍入的答案。

C 可运行示例

IEEE 754的C实现是否做了额外的事情?还是我错过了完全不同的东西。

更新

由于拼写错误,我发布的代码示例已损坏。试试这个修复了 C 可运行示例

但最初的问题仍然存在。

double d1, d2, d3;
d1 = 0.1;    d2 = 0.2;    d3 = d1 + d2;
printf ("%d'n", ((((double)0.1)+((double)0.2)) == ((double)d3)));
printf ("%.17f'n", d1+d2);
printf ("%d'n", ((d1+d2) == d3));

输出为

1
0.30000000000000004
1

现在改写的问题是:

  1. 为什么(以及何时以及如何)C编译器冒昧

    地说

    0.3 ==

    0.30000000000000004
  2. 考虑到所有事实,难道不是C实现被破坏了,而不是Javascripts的吗?

为什么(以及何时以及如何)C编译器冒昧

地说
    0.3 == 0.30000000000000004

考虑到所有事实,难道不是C实现被破坏了,而不是Javascripts的吗?

其实不然。

给出的输出来自以下代码:

printf ("%d'n", ((((double)0.1)+((double)0.2)) == ((double)d3)));

但你写道:

d1 = 0.1;    d2 = 0.2;    d3 = d1 + d2;

所以d3不是0.3,而是0.30000000000000004

`printf("%d'n", (0.1+0.2) == 0.3);`

这些是双倍而不是浮点数。

做:

printf("%d'n", (0.1+0.2) == 0.3);
printf("%d'n", (0.1f+0.2f) == 0.3f);

瞧!

http://codepad.org/VF9svjxY

Output:
0
1

看看这个问题。这是关于其他的,但是使用GCC的ppl与使用MSVC的ppl得到的结果不同。打印浮点数的整数

您的示例代码使用 1、2 和 (1+2),它们都可以在双精度浮点中完全表示。 另一方面,0.1 在浮点数中不能完全表示,因此您可以获得该数字的近似值。当将大约 0.1 添加到大约 0.2 时,你会得到大约 0.3,但这是否与编译器在表示 0.3 时会选择的完全相同的近似值谁能分辨。

表示形式使用二进制。这意味着它使用 1/2、1/4、1/8、1/16、1/32(依此类推,精度很高......这意味着 0.5、0.25 等完全能够表示。不是二进制分数的精确总和的数字可以非常接近地近似。

解决方案:不要将浮点数相互比较。将它们的差异与您不关心的小数字进行比较。

#define EPSILON 0.000001
printf("%d", fabs((0.1+0.2) - 0.3 ) < EPSILON );

我不确定为什么C代码有效而python/javascript不起作用。这是魔术。但希望这无论如何都能回答你的问题。