我正在查看git中的_math.c(第25行):
#if !defined(HAVE_ACOSH) || !defined(HAVE_ASINH)
static const double ln2 = 6.93147180559945286227E-01;
static const double two_pow_p28 = 268435456.0; /* 2**28 */
我注意到ln2的值和ln2的whatwolframalpha值不同。(秃顶是区别)
ln2=0.693147180559945286227(cpython)
ln2=0.6931471805599453094172321214581(沃尔夫拉马尔法)
ln2=0.693147180559945309417232121458(维基百科)
所以我的问题是为什么会有区别?我错过了什么?在
如user2357112所述,此代码来自FDLIBM。这是为IEEE-754机器精心编写的,其中C双精度有53位。它并不真正关心2的实际日志是什么,而是非常关心
log(2)
的最佳53位近似值。在要重现预期的53位精确值,17 decimal digits would have sufficed。在
那么为什么他们用21位小数呢?我的猜测是:21位小数是保证转换后的结果正确到64位精度所需的最小值。如果编译器以某种方式决定将文本转换为Pentium的80位浮点格式(精度为64位),那么这在当时可能是个问题。在
因此,他们用足够的十进制数字显示53位结果,这样如果它被转换成精度为64位的二进制浮点格式,那么后面的11位(=64-53)将全部为零,从而确保他们从一开始就使用他们想要的53位值。在
在英语中,
x
是log(2)
的53位精确值,y
是将代码中的十进制字符串转换为精度为64位的二进制浮点格式的结果。它们是一样的。在在当前的现实中,我希望所有的编译器都能将文本转换成本地的IEEE-754双精度格式,精度为53位。在
无论哪种方式,代码都确保使用
log(2)
的最佳53位近似值。在在二进制64浮点表示的精度范围内,这些值相等:
^{pr2}$0.693147180559945286227
是将ln(2)最精确的可表示近似值存储到一个64位浮点中,然后将其打印到那么多个数字。尝试在浮点中填充更多的数字只会使结果四舍五入到相同的值:至于他们为什么在代码中写
0.693147180559945286227
,你得问问1993年在Sun上写FDLIBM的人。这个代码来自FDLIBM。在Python似乎错了,尽管我不确定这是一个疏忽,或者它有更深的含义。21点的解释似乎合理,但我不明白,为什么他们会给出错误的数字。在
您可以使用More efficient series下的公式自己检查。在Mathematica中,你可以用
使用
^{pr2}$N[log2,30]
可以得到正确的数字它支持Wikipedia和W | A的正确性。如果您愿意,您可以对机器精度数字进行相同的计算。在Mathematica中,这通常意味着
double
。在请注意,这段代码完全编译为普通的迭代,并且不使用一些减少错误的求和方案。所以没有神奇的编译
Sum
函数。在我的机器上显示:在你指出的数字范围内都是正确的。这有21点建议的精度
编辑
正如在注释和答案中指出的,您在
_math.c
中看到的值可能是53位表示相关问题 更多 >
编程相关推荐