以下程序的结果对我的计算机有些奇怪。
#include <iostream>
using namespace std;
int main(){
double a = 20;
double b = 0.020;
double c = 1000.0;
double d = b * c;
if(a < b * c)
cout << "a < b * c" << endl;
if(a < d)
cout << "a < d" << endl;
return 0;
}
输出:
$ ./test
a < b * c
我知道双重的精确性并不准确。但是我不希望该价值改变并给出不一致的比较结果。
如果被打印出来,我确实希望也应该印刷。但是,当我在i686服务器甚至Cygwin上运行此代码时。我可以看到
a < b * c
,但看不到
a < d
。
该问题已被确认为平台依赖。这是由双重分配的不同指令和实施引起的吗?
update
生成的组装:
a < b * c
型:您可能正在看到80位Intel FPU的影响。
在定义a < d
main:
.LFB1482:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
subl $56, %esp
.LCFI2:
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $0, -8(%ebp)
movl $1077149696, -4(%ebp)
movl $1202590843, -16(%ebp)
movl $1066695393, -12(%ebp)
movl $0, -24(%ebp)
movl $1083129856, -20(%ebp)
fldl -16(%ebp)
fmull -24(%ebp)
fstpl -32(%ebp)
fldl -16(%ebp)
fmull -24(%ebp)
fldl -8(%ebp)
fxch %st(1)
fucompp
fnstsw %ax
sahf
ja .L3
jmp .L2
//.L3 will call stdout
以80位精度计算,并在将其存储到b * c
otoH,使用表达式
d
,在离开FPU之前,您的80位算术结果(a < d)
直接与a
进行比较。因此,d
结果从未通过保存在64位变量中而获得精确剪辑。
您必须查看生成的说明,我希望这会随编译器版本和优化器标志而变化。
我不确定AS3机器是哪种类型的硬件,但是例如,您可以在机器中看到这种行为,其中内部浮点单元使用大于64位的浮子来存储中间结果。 在X86拱门的情况下,X87浮点单元(但没有SSE)就是这种情况。 问题是处理器将加载
(a < b * c)
和
b * c
浮点寄存器,然后进行乘法并将临时结果存储在寄存器中。如果此寄存器大于64位,则结果将与计算并存储回存储的a
(或b*c
)不同,迫使它们为64位。
这是许多情况的一种情况,您需要查看您的装配代码,以确定正在发生的事情。 您还需要了解硬件如何在内部处理浮点计算。Windows Machine上使用MINGW的代码快速测试会产生这些完全相同的结果。 不过,真正奇怪的是,如果我将双打更改为浮子,一切都会按原样运行(根本没有输出)。 但是,如果我将它们更改为长双打,则“ a” 我的猜测可能是因为双打应该允许更精确,在乘以两个直接值并进行比较时,有些奇怪的事情正在发生,而不是存储结果以备以后? 这也可以解释为什么最终出现的问题也会出现长时间,因为它们需要更多的内存空间。