![](/img/trans.png)
[英]C programming: translated function from MATLAB to C gives slightly (but significantly) different result
[英]Slightly different result from exp function on Mac and Linux
以下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)));
}
在Mac上的输出是
x19 = 9.207186811339878e+29
x19 hex = 46273e0149095886
在Linux上
x19 = 9.207186811339876e+29
x19 hex = 46273e0149095885
两者都编译时没有任何优化标志,如下所示:
gcc -lm ....
我知道我绝不应该将浮点数完全相同。
这个问题是在调试过程中出现的,令人遗憾的是,使用该计算证明的算法在数值上是不稳定的,并且这种微小的差异导致最终结果出现明显的偏差。 但这是一个不同的问题。
令我惊讶的是, exp
等基本操作未标准化,正如我对IEEE 754指定的基本代数操作所期望的那样。
对于不同机器或不同版本的libm
不同实现,是否可以依靠精度进行任何假设?
由于下面的讨论,我使用了mpmath
来计算比机器精度更高的值,并且再得到两个数字,结果为9.2071868113398768244
,所以对于我的两个结果,最后一个数字已经是错误的了。 linux上的结果可以通过对该值进行四舍五入来解释;如果计算机使用四舍五入,Mac结果也将关闭。
C99规范指出(其他版本应该相似):
J.3实现定义的行为
1需要一个一致的实现来记录其在本子节中列出的每个区域中的行为选择。 以下是实现定义的内容:
...
J.3.6浮点数
—浮点运算和
<math.h>
和<complex.h>
中返回浮点结果的库函数的准确性(5.2.4.2.2)。
意味着GNU libm和BSD libm可以自由地具有不同级别的准确性。 可能发生的情况是,OSX上的BSD实现四舍五入到最近的ULP(最后一个单元),而GNU实现截短到下一个ULP。
IEEE-754行为是在二进制级别上指定的。 使用Linux,我获得了Python的本地math
库mpmath
和MPFR相同的值(通过gmpy2
)。 但是,在三种方法之间,转换为十进制会有所不同。
>>> import mpmath, gmpy2
>>> import mpmath, gmpy2, math
>>> x18=68.99495205106946
>>> x19=math.exp(x18)
>>> mp18=mpmath.mpf("68.99495205106946")
>>> mp19=mpmath.exp(mp18)
>>> gp18=gmpy2.mpfr("68.99495205106946")
>>> gp19=gmpy2.exp(gp18)
>>> x18 == mp18
True
>>> x18 == gp18
True
>>> x19 == mp19
True
>>> x19 == gp19
True
>>> print(x18, mp18, gp18)
68.99495205106946 68.9949520510695 68.994952051069461
>>> print(x19, mp19, gp19)
9.207186811339876e+29 9.20718681133988e+29 9.2071868113398761e+29
转换为Python的任意精度整数形式后,所有三个结果也显示为精确。
>>> hex(int(x19))
'0xb9f00a484ac42800000000000'
>>> hex(int(mp19))
'0xb9f00a484ac42800000000000'
>>> hex(int(gp19))
'0xb9f00a484ac42800000000000'
因此(至少一个)Linux数学库mpmath
和gmpy2.mpfr
同意。
免责声明:我维护gmpy2
并在过去为mpmath
做出了贡献。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.