簡體   English   中英

x86 和 x64 上 pow 的不同結果

[英]Different results for pow on x86 and x64

我想知道為什么我分別在 x86 和 x64 上使用pow時會觀察到不同的結果。 在我們的應用程序中,我們控制浮點舍入模式,它在 Windows 和 Linux 32 位上都運行良好。

#include <cmath>
#include <cstdio>
#include <cfloat>

void checkEqual(double expected, double observed) {   
    if (expected == observed) {
        printf("Expected %.23f, got %.23f\n", expected, observed);
    }
    else {
        printf("ERROR: Expected %.23f, got %.23f\n", expected, observed);
    }
}

int main(int argc, char **argv) {   
    unsigned ret, tmp;
    _controlfp_s(&ret, 0, 0);
    _controlfp_s(&tmp, RC_DOWN, MCW_RC);

    checkEqual(2048.0, pow(2.0, 11.0));
    checkEqual(0.125, pow(2.0, -3.0));

    return 0;   
}

使用 Visual Studio 2015 編譯和運行(2012 給出相同的結果)給我以下輸出

x86:

Expected 2048.00000000000000000000000, got 2048.00000000000000000000000
Expected 0.12500000000000000000000, got 0.12500000000000000000000

x64:

ERROR: Expected 2048.00000000000000000000000, got  2047.99999999999977262632456
ERROR: Expected 0.12500000000000000000000, got 0.12499999999999998612221

任何人都可以解釋這些差異嗎? 我知道,浮點計算本質上並不精確,但對於這些特定值,我希望函數無論舍入模式如何都能產生相同的結果。


我對此進行了更多調查,發現真正的問題不是pow的實現方式,而是 x86 和 x64 硬件與 Hans Passant 建議的不同。

pow可能有許多不同的實現。 例如, pow(x,y)exp(y*ln(x)) 可以想象,即使xy是完全可表示的, exp(11.0*ln(2.0))也會受到內部舍入誤差的影響。

但是,使用整數參數調用pow是很常見的,因此一些庫針對這些情況優化了路徑。 例如, pow(x,2*n)pow(x,n)平方,而pow(x, 2n+1)x*pow(x, 2n)

在這方面,您的 x86 和 x64 實現似乎有所不同。 那可能發生。 IEEE 只承諾 +-*/ 和 sqrt 的精確結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM