为什么双重价值在分配后似乎会更改?

问题描述 投票:0回答:1

以下程序的结果对我的计算机有些奇怪。

#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位精度计算,并在将其存储到
c++ architecture
1个回答
5
投票
中时将其舍入到64位。

b * c

将将64位与64位比较。

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” 我的猜测可能是因为双打应该允许更精确,在乘以两个直接值并进行比较时,有些奇怪的事情正在发生,而不是存储结果以备以后? 这也可以解释为什么最终出现的问题也会出现长时间,因为它们需要更多的内存空间。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.