我在某些平台上观察到不正确的(IMO)舍入行为,如下所示:
在取整模式下将log(2)
的值计算为FE_DOWNWARD
和FE_UPWARD
(请参阅<fenv.h>
)。在我所看到的所有情况下,向下舍入的结果都小于向上舍入的结果,这是我所期望的(结果不准确)。
现在使用相同的舍入模式,对每个结果调用exp
。由于exp
是单调递增的(在感兴趣区域中的坡度为〜2),所以我希望这些结果会进一步分开。但是在某些经过测试的平台上,exp
的两个结果是等效的。
这是一个简单的测试程序:
#include <stdio.h>
#include <math.h>
#include <fenv.h>
int main(void) {
fesetround(FE_DOWNWARD);
double xlo = log(2);
double xxlo = exp(xlo);
printf("xlo=%.16e xxlo=%.16e\n",xlo,xxlo);
fesetround(FE_UPWARD);
double xhi = log(2);
double xxhi = exp(xhi);
printf("xhi=%.16e xxhi=%.16e\n",xhi,xxhi);
printf("Delta x=%.16e\n",xhi-xlo);
if (xxlo == xxhi)
printf("FAIL\n");
else
printf("Delta xx=%.16e\n",xxhi-xxlo);
return 0;
}
至强E5520 @ 2.27GHz上的一个(良好)结果:
xlo=6.9314718055994528e-01 xxlo=1.9999999999999997e+00
xhi=6.9314718055994540e-01 xxhi=2.0000000000000005e+00
Delta x=1.1102230246251566e-16
Delta xx=6.6613381477509393e-16
已通过测试的其他处理器:AMD Ryzen 9 3950X,Intel i7-5557U,Intel i7-3770,Intel m7-6Y75。
但是据报道,一对夫妇失败了(xxlo == xxhi):Intel E5-2650和AMD EPYC 7401,碰巧都是服务器级机器。我没有直接访问这些证书的权限,但是在https://repl.it/languages/c上运行测试也失败了:
clang version 7.0.0-3~ubuntu0.18.04.1 (tags/RELEASE_700/final)
clang-7 -pthread -lm -o main main.c
./main
xlo=6.93147180559945286e-01 xxlo=2.00000000000000000e+00
xhi=6.93147180559945398e-01 xxhi=2.00000000000000000e+00
Delta x=1.11022302462515655e-16
FAIL
我对结果的实际精度不太感兴趣,但对相对值更感兴趣。那我是不是错过了什么,还是只是错了?如果是错误的,是硬件舍入错误还是软件数学库甚至编译器/设置出现问题?我也有兴趣收集运行简单测试的结果,看看是否可以从该数据中得出其他结论。
请提供数字的十六进制;通过避免bin dec转换(在某些计算机上似乎也有缺陷),这应该是确定的。
我所说的话都没有使您的结论是服务器的硬件不一致,因此IEEE实施存在缺陷。
哦,还有一件事;通过查看日志后消除exp来检查优化器是否工作太辛苦。或者也许使用FMA,有时会给您[[更好
舍入错误。