天天看點

如何用查表替代運算

對于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的高幾位來降低表的長度。