不知道有没有人知道像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...
这是一个有点难度的问题, 因为现成的公式:
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
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...
这是一个有点难度的问题, 因为现成的公式:
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
http://community.csdn.net/Expert/TopicView3.asp?id=5037109