[英]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))
。 可以想象,即使x
和y
是完全可表示的, 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.