在 C++ 中,
double x = 1.0;
double y = x / 3.0;
if (x == y * 3.0)
cout << " They are equal!" ;
else
cout << " They are NOT equal." ;
将打印
‘They are NOT equal.’
正如预期的那样,由于 1/3 的非精确表示为有限大小尾数的(二进制)数。 但是在 Python 中(在 https://repl.it/repls/MessyJaggedMouse 上),
x = 1.0
y = x / 3.0
x == y * 3.0
打印
True
Python 何时以及为何偏离上述预期行为?编辑:Python 不会离开 - 请参阅下面我的回答。
最佳答案
只有当我在 C 中使用 x87 数学时才会发生这种情况。
正确舍入,使用 IEEE 754 double 运算,您将得到 true。
但是,如果您以更高的精度计算中间值,则可能会得到 false。 C 不需要以 64 位精度计算所有中间值,并且在具有 x87 浮点指令的 32 位 x86 处理器上,您最终将使用较大的 80 位浮点类型作为中间值。根据启用的优化设置和编译器的详细信息,计算将以不同的方式完成(使用不同的中间值),您将得到略有不同的结果。
#include <cstdio>
int main() {
double x = 1.0;
double y = x / 3.0;
std::printf("x == y * 3.0: %s\n", x == y * 3.0 ? "true" : "false");
return 0;
}
使用 GCC,如果使用 -mfpmath=387 -O0
编译,我会看到 false
。如果我在没有 -mfpmath=387
的情况下进行编译(在 AMD64 上这将默认为 SSE 而不是)或者如果我使用 -O2
进行编译,我会看到 true
。
您可以在 GodBolt 上使用 x87 指令查看它是如何编译的:https://godbolt.org/z/rf1Rir -- 尝试添加 -O2
或删除 -mfpmath=387
以查看它如何影响生成的代码。
请注意,(1.0/3.0) * 3.0 == 1.0
有点巧合。您可以在 Python 中测试以下代码,例如:
1.0 / 49.0 * 49.0 == 1.0
这应该给出 False
。
关于Python C++ float 学表示错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54424331/