天天看点

如何用查表替代运算

对于sin,cos,tan等三角函数来说,使用cpu/fpu计算所花费的时间比加减法员算要慢很多的时间

这就使得在很多密集的三角运算花费了大量的时间,如何在保证一定精度的情况下,使用近似的方法来获取这些函数的数值呢

常规的做法,就是牺牲空间换取时间的查表法

需要注意的是,查表法不是万能的,必须针对特定的函数特殊处理,拿sin(x)作为例子来说

把x从0到90度,每0.01一个单位,把每个点的sin数值计算出来,存储到一个长度9000的表当中去

那么这个时候的精度是0.01吗?

不是

精度说的是,sin(x)的实际数值和查表获得的数值之间的差,要控制精度,就要按照精度来划分值域空间而不是定义域空间,sin(x)在0-90的定义域内值域是0到1,按照0.01划分,只需要100个数值就是了

建立一个长度100的表,把0到1之间的值域分割点的asin数值写入其中(显然表内数据不是等间距的)

具体的计算x的时候,检查这个表,找到x位于哪两个下标所对应的范围内,从而根据下标×0.01获得对应的sin数值。

但是这个查表显然和第一种方式的查表的速度无法相比

如果,对于给定的精度,我们能够确定一个最小的间隔,以这个间隔来划分定义域的话就好了

其实这个问题很好解决,我们可以通过计算导数来判断sin函数,在什么地方数值变化最大,也就是导数数值最大,显然sin的导数是cos,在0的时候最大

因此假定精度是0.01,我们只要计算asin(x)=0.01,x=0.057,为了方便我们取0.05作为间隔,把0到90度的定义域均分成为180份就可以了

对比一下,可以发现,如果直接按照0.01的精度划分定义域,需要9000表长

如果按照精度0.01划分值域,需要表厂100,但是查表的时间不容忽视

按照上述方法,需要180表长,效率一样。

一个特殊函数的查表法:

对于lnx函数,我们知道是可以用 log2(x)/ln(2)的方式来计算

x = 1.m ×2^N

log2对于pc计算机来说,可以通浮点数的内存结构直接提取出来log2的整数部分N,

对于尾数部分,我们建立一个1.0到2.0之间的尾数表,通过浮点数在pc当中的内存结构获取到x的小数部分m,然后直接把他转化成为整数作为表的索引数值就可以了。这样的表的精度一点都不损失。

还可以根据实际的精度要求,只选择m的高几位来降低表的长度。