0.简介
最近在复习一些数学知识,对计算机如何log,sin,cos等有了些疑问,并且通过查阅资料(其实没找到什么),和设计方法,大概将其实现出来。
1.泰勒展开
对于如何计算log这个问题,我能想到的就是去计算泰勒展开式,将在0点展开,但是发现0点没法展开,那就变换一下,展开。
经过推到,其泰勒展开式为,有了这个展开式,我们就可以计算的结果。
2.实际问题,大于1的数字
上面虽然得到了泰勒展开,但是展开只能拟合到(-1,1]这个范围内,超出这个范围,尤其是大于1的时候,会随着值得增大而越发的不准确,这就引入了一个问题,大于1的怎么算?经过一番思考,我给出了如下解决方案,既然无法计算大于1的,那就计算小于1的数字了,比如计算的时候,将其变换为,这个根据运算规则来算,可以拆解为,这样一看,可以用泰勒展开计算了,然后,这样一来就解决了大于1的计算,方法就是将大于1的数a除以一个比a大的且最近的,这样一来a可以将范围变换在(0,1]内,并且可以很容易的求log2。
3.实际问题,接近0的数字
实际上,我已经开始实现上述方案了,但是实现之后遇到了一个问题,就是接近0的数字很难准确逼近,比如0.00001可能需要展开999项能逼近,那么0.0000000001就需要展开9999999项才能逼近,甚至不能逼近,导致接近于0的数字需要展开很多项才能计算,并且数字越小,要求项数越多,计算时间越长,这显然不是一个好办法,经过上面的思路,我发现0.0005可以表示成0.1*0.1*0.1*0.5,,这样一来,一个很小的数字可以变换到(0,1]之间来,这样就不用费力的去拟合0.00001这种数字了,可以通过(0,1]之间的结果组合出来。
4.优化
有了上面的思想后,就可以实现了,这里为了优化,希望能减小泰勒展开式的项数同时还能保证准确,我发现泰勒展开在接近1的位置越容易准确,所以尽量计算1附近的拟合,所以在计算0.1的时候,可以放大计算0.8,这样一来可以如下表示,,这样时候,比如同样是20项目展开,计算0.8比0.1要准确。然后尽可能的让0.1234这种比较小的数字接近1,所以我将小于0.5的数字不断乘以2,直到其接近1且小于1的时候停止,记录乘的2的个数,即,然后[0.5,1]之间的结果直接用泰勒拟合就可以了。