现在的位置: 首页 > 综合 > 正文

log1p(x) 函数的实现 (续)

2014年03月21日 ⁄ 综合 ⁄ 共 725字 ⁄ 字号 评论关闭

几个月前写过一篇文章《log1p(x) 和 expm1(x) 函数的实现

http://blog.csdn.net/liyuanbhu/article/details/8544644

当时给出了个 GSL 的 log1p(x) 的代码实现。不过当时没想明白为什么要那样算,最近在水木上看一个帖子时突然就领悟了。

GSL 上的代码如下:

double gsl_log1p (const double x)  
{  
   volatile double y, z;  
   y = 1 + x;  
   z = y - 1;  
   return log(y) - (z - x) / y ;  /* cancels errors with IEEE arithmetic */  
}  

我们知道计算机上的浮点数是只有有限的精度的。

所以 y:=1+x 这条赋值语句当x较小时算出的y并不精确等于1+x。

或者可以这样认为,我们实际计算的是

y:1+x'

而x’ 就是计算1+x 时小数点对其的过程种x有效位数损失后的结果。 

因此,直接计算 log(1+x) 实际上是计算了 log(1+x')

由于 与 x' 很接近,所以下面的式子近似成立:

上面的式子变一下型就得到:

这也就是GSL 上采用的代码了(x’ 对应代码中的z)

多说一句,在C程序中不能写为:

z= 1+x-1;

否则编译器会自作聪明的优化成 z = x,并且似乎无法通过编译器的编译选项关掉这种优化。

另外,有一篇很有名的文章,What Every Computer Scientist Should Know About Floating-Point Arithmetic,上面也探讨了这个计算。并且给出了另一个计算方法。

这个算法的依据在于当 x 与 x’ 很接近时,

x(x’-x)的值非常小,所以这种算法的误差很小。

抱歉!评论已关闭.