求救!自然对数ln(x)的算法是什么?

时间:2021-09-30 18:35:49
太勒展开就算了,因为考虑到展开点的选取问题,当ln(x)函数x<0.1时,函数值随X的减小迅速的减小并趋向负无穷。因此X<0.1时太勒展开只能近似展开点附近很小区域的函数值。
不知道有没有人知道像C语言自带的数学函数库那样高效快速的ln(x)算法。

3 个解决方案

#1


[ZT]

这是一个有点难度的问题, 因为现成的公式:

    ln(1+x)=x-x^2/3+x^3/3-...(-1)^(k-1)*x^k/k+...      ( |x|<1 )   ①

不满足计算其整个定义域的要求.
 
幸好, 有一个双曲线余弦函数与自然对数的关系式:

   ln(x) = 2 arctanh((x-1)/(x+1))                      ②

而 arctanh(y)= y + y^3/3 + y^5/5 + ...       (y≤1)    ③

我们先稍微研究一下②式的性质.

设 y=(x-1)/(x+1), 则②式化为ln(x) = 2 arctanh(y).

对于函数 y=(x-1)/(x+1) , 当 x 增大时 y 永远也大不过 1 ,完全可以用③式计算, 但是 x 较大时 y 非常接近 1 ,使得级数③,的高精度计算非常慢. 只有当 y 接近 0 (x 接近 1) 时, 速度才快.

想到对数的性质:

   ln(x)=y+ln(x/e^y)      (y 是任意实数)           ④

这样就可以通过选择适当的 y 值使 x/e^y 尽量接近1,从而方便使用①或②③式来计算.并且 x 以相同程度接近 1 时(x-1)/(x+1)比(x-1)更有利. 且③比①收敛得更快.因此建议使用②③式来计算.

 

剩下的问题是如何找这个 y .

y 应该是 ln(x) 近似值.因为这样才能使 ln(x)-y 尽可能地接近 ln(1) .

联想到常用对数的一个性质:

   lg(x)=x 的位数 -1+lg(x的小数点移至其第一位后的数)

事实上它是④式的特例. 当 x 以非十进制表示时(例如二进制)上式稍加修改就可以用:

   log(x)=x的位数-1+log(x的小数点移至其第一位后的数)

接着用换底公式 ln(x)=log(x)/log(e) 这个问题就解决得差不多了, 通常 log 的底取的与内部的进位制一样, 比如 2, 10, 65536, 1000000000...
 

#2


恩,楼上的方法貌似不错,我再研究研究。。。

#3


cordic算法也很快:

http://community.csdn.net/Expert/TopicView3.asp?id=5037109

#1


[ZT]

这是一个有点难度的问题, 因为现成的公式:

    ln(1+x)=x-x^2/3+x^3/3-...(-1)^(k-1)*x^k/k+...      ( |x|<1 )   ①

不满足计算其整个定义域的要求.
 
幸好, 有一个双曲线余弦函数与自然对数的关系式:

   ln(x) = 2 arctanh((x-1)/(x+1))                      ②

而 arctanh(y)= y + y^3/3 + y^5/5 + ...       (y≤1)    ③

我们先稍微研究一下②式的性质.

设 y=(x-1)/(x+1), 则②式化为ln(x) = 2 arctanh(y).

对于函数 y=(x-1)/(x+1) , 当 x 增大时 y 永远也大不过 1 ,完全可以用③式计算, 但是 x 较大时 y 非常接近 1 ,使得级数③,的高精度计算非常慢. 只有当 y 接近 0 (x 接近 1) 时, 速度才快.

想到对数的性质:

   ln(x)=y+ln(x/e^y)      (y 是任意实数)           ④

这样就可以通过选择适当的 y 值使 x/e^y 尽量接近1,从而方便使用①或②③式来计算.并且 x 以相同程度接近 1 时(x-1)/(x+1)比(x-1)更有利. 且③比①收敛得更快.因此建议使用②③式来计算.

 

剩下的问题是如何找这个 y .

y 应该是 ln(x) 近似值.因为这样才能使 ln(x)-y 尽可能地接近 ln(1) .

联想到常用对数的一个性质:

   lg(x)=x 的位数 -1+lg(x的小数点移至其第一位后的数)

事实上它是④式的特例. 当 x 以非十进制表示时(例如二进制)上式稍加修改就可以用:

   log(x)=x的位数-1+log(x的小数点移至其第一位后的数)

接着用换底公式 ln(x)=log(x)/log(e) 这个问题就解决得差不多了, 通常 log 的底取的与内部的进位制一样, 比如 2, 10, 65536, 1000000000...
 

#2


恩,楼上的方法貌似不错,我再研究研究。。。

#3


cordic算法也很快:

http://community.csdn.net/Expert/TopicView3.asp?id=5037109