问题描述
我正在 32 位和 64 位平台上编译和运行以下程序:
I'm compiling and running the following program in 32 and 64 bit platforms:
int main()
{
double y = 8.34214e08;
double z = 1.25823e45;
return y * z == 8.34214e08 * 1.25823e45;
}
虽然在 64 位中结果是预期的(值相同且退出代码为非零),但在 32 位中似乎在编译时计算的值之间存在一些差异,比较的右侧,左侧在运行时计算.
While in 64bit the result is the expected (the values are the same and the exit code is non-zero) in 32bit seems there is a little difference between the value calculated at compile time, the right hand side of the comparison, and the left side computed at runtime.
这是编译器中的错误还是有逻辑解释?
Is this a bug in the compiler or there is a logical explanation?
这与 为什么比较 double 和 float 会导致意外结果? 因为这里的所有值都是 double.
this is different from Why comparing double and float leads to unexpected result? because here all the values are double.
推荐答案
IEEE-754 允许以更高的精度完成中间计算(重点是我的).
IEEE-754 allows intermediate computations to be done in a greater precision (emphasis mine).
(IEEE-754:2008) 语言标准还应定义并要求实现提供允许和禁止对块进行单独或共同的值更改优化的属性.这些优化可能包括但不包括仅限于:[...] 在表达式评估中使用更广泛的中间结果."
在您的情况下,例如在 IA-32 上,双精度值可以以更高的精度(80 位而不是 64 位)存储在 x87 FPU 寄存器中.所以你实际上是在比较双精度上的乘法和双扩展精度上的乘法.
In your case for example on a IA-32, the double values could be stored in the x87 FPU registers with greater precision (80-bit instead of 64). So you are actually comparing a multiplication done on double precision with a multiplication done on double-extended precision.
例如,在结果为 1
的 x64 上(不使用 x87 FPU,而是使用 SSE),添加 gcc
选项 -mfpmath=387
使用 x87 使结果更改为 0
在我的机器上.
For example, on x64 where the result is 1
(the x87 FPU is not used as SSE is used instead), adding gcc
option -mfpmath=387
to use the x87 makes the result change to 0
on my machine.
如果你想知道 C 是否也允许这样做,它是:
And if you wonder if that is also allowed by C, it is:
(C99, 6.3.1.p8)浮点操作数的值和浮点表达式的结果可以比类型要求的精度和范围更高;"
这篇关于双乘在 32 位平台上的编译时和运行时不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!