计算机与代数---如何计算log---方法推理[1]

0.简介

最近在复习一些数学知识,对计算机如何log,sin,cos等有了些疑问,并且通过查阅资料(其实没找到什么),和设计方法,大概将其实现出来。

1.泰勒展开

对于如何计算log这个问题,我能想到的就是去计算泰勒展开式,将log_{2}(x)在0点展开,但是发现0点没法展开,那就变换一下,展开log_{2}(x+1)

经过推到,其泰勒展开式为(x-\frac{x^{2}}{2}+\frac{x^{3}}{3}-\frac{x^{4}}{4}...)/ln2,有了这个展开式,我们就可以计算log_{2}(x+1)的结果。

2.实际问题,大于1的数字

上面虽然得到了泰勒展开,但是展开只能拟合到(-1,1]这个范围内,超出这个范围,尤其是大于1的时候,会随着值得增大而越发的不准确,这就引入了一个问题,大于1的怎么算?经过一番思考,我给出了如下解决方案,既然无法计算大于1的,那就计算小于1的数字了,比如计算log_{2}(31)的时候,将其变换为log_{2}(\frac{31}{32}\ast 32),这个根据运算规则来算,可以拆解为log_{2}(\frac{31}{32})+log_{2}(32),这样一看,log_{2}(\frac{31}{32})可以用泰勒展开计算了,然后log_{2}(32)=5,这样一来就解决了大于1的计算,方法就是将大于1的数a除以一个比a大的且最近的2^{n},这样一来a可以将范围变换在(0,1]内,并且2^{n}可以很容易的求log2。

3.实际问题,接近0的数字

实际上,我已经开始实现上述方案了,但是实现之后遇到了一个问题,就是接近0的数字很难准确逼近,比如0.00001可能需要展开999项能逼近,那么0.0000000001就需要展开9999999项才能逼近,甚至不能逼近,导致接近于0的数字需要展开很多项才能计算,并且数字越小,要求项数越多,计算时间越长,这显然不是一个好办法,经过上面的思路,我发现0.0005可以表示成0.1*0.1*0.1*0.5,log_{2}(0.0005)=log_{2}(0.1*0.1*0.1*0.5)=3*log_{2}(0.1)+log_{2}(0.5),这样一来,一个很小的数字可以变换到(0,1]之间来,这样就不用费力的去拟合0.00001这种数字了,可以通过(0,1]之间的结果组合出来。

4.优化

有了上面的思想后,就可以实现了,这里为了优化,希望能减小泰勒展开式的项数同时还能保证准确,我发现泰勒展开在接近1的位置越容易准确,所以尽量计算1附近的拟合,所以在计算0.1的时候,可以放大计算0.8,这样一来可以如下表示,log_{2}(0.1)=log_{2}(0.1*8)-3,这样时候,比如同样是20项目展开,计算0.8比0.1要准确。然后尽可能的让0.1234这种比较小的数字接近1,所以我将小于0.5的数字不断乘以2,直到其接近1且小于1的时候停止,记录乘的2的个数,即log_{2}(m*2^{n})=log_{2}(m)-n,然后[0.5,1]之间的结果直接用泰勒拟合就可以了。

下一篇,C++实现log计算

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值