与Mac和Linux上的exp函数略有不同

roc*_*ker 8 c linux precision macos numeric

以下C程序在我的Mac和Linux上产生不同的结果.我很惊讶,因为我认为实施libm是以某种方式标准化的

#include<math.h>
#include<stdio.h>

int main()
{
  double x18=-6.899495205106946e+01;
  double x19 = exp(-x18);
  printf("x19     = %.15e\n", x19);
  printf("x19 hex = %llx\n", *((unsigned long long *)(&x19)));
}
Run Code Online (Sandbox Code Playgroud)

Mac上的输出是

x19     = 9.207186811339878e+29
x19 hex = 46273e0149095886
Run Code Online (Sandbox Code Playgroud)

在Linux上

x19     = 9.207186811339876e+29
x19 hex = 46273e0149095885
Run Code Online (Sandbox Code Playgroud)

两者都编译时没有任何优化标志,如下所示:

gcc -lm ....
Run Code Online (Sandbox Code Playgroud)

我知道我永远不应该比较漂浮物.

在调试期间出现了这个问题,遗憾的是使用这种计算证明的算法在数值上不稳定,这种微小的差异导致最终结果的显着偏差.但这是一个不同的问题.

令我感到惊讶的是,这些基本操作exp并未标准化,因为我可以期待IEEE 754规定的基本代数运算.

libm对于不同机器或不同版本的不同实现,是否有任何关于精度的假设?


由于下面的讨论我曾经mpmath计算过高于机器精度的值,我得到两个数字的结果9.2071868113398768244,所以对于我的两个结果,最后一个数字已经错了.linux上的结果可以通过向下舍入此值来解释,如果计算机使用四舍五入,则Mac结果也会关闭.

dla*_*lle 2

C99 规范指出(其他版本应该类似):

\n\n
\n

J.3 实现定义的行为

\n\n

1 需要一个一致的实现来记录其在本节列出的每个领域中的行为选择。以下是实现定义的:

\n\n

...

\n\n

J.3.6 浮点

\n\n

\xe2\x80\x94 中的浮点运算以及返回浮点结果的库函数的精度<math.h>( <complex.h>5.2.4.2.2)。

\n
\n\n

这意味着 GNU libm 和 BSD libm 可以自由地具有不同级别的精度。\n可能发生的情况是,OSX 上的 BSD 实现舍入到最近的(最后一个单位)ULP,而 GNU 实现则截断到下一个 ULP。

\n