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 %.23fn", expected, observed);
}
else {
printf("ERROR: Expected %.23f, got %.23fn", 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的精确结果。
相关文章:
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- valgrind-hellgrind与泄漏检查的结果不同
- 用C++20 fmt限制结果的总大小
- 如何返回一个类的两个对象相加的结果
- 使用QProcess执行命令,并将结果存储在QStringList中
- 如果我std::dynamic_pointer_cast并且底层dynamic_cast的结果为null,那么返回的sh
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 序列化,没有库的整数,得到奇怪的结果
- C++将pow函数的双结果强制转换为整数
- x86和x64上pow的不同结果
- C 中的 pow() 函数给我带来了错误的结果
- 在 C++ 中使用 pow() 没有得到预期的结果
- 用双精度计算 pow 会给出错误的结果
- C ++或C Pow给出错误的结果
- std::pow在32位和64位应用程序中产生不同的结果
- pow()在使用类型转换时会产生意外结果
- 调用pow()时四舍五入结果的差异
- 使用sqrt()和pow()函数会产生不同的结果
- C++pow函数得到了一个奇怪的结果
- C++ POW(X,Y) X 负双精度和 Y 负双精度,结果给出 nan