久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

arctan()函數(shù)的查表算法

 haishukongmu 2018-07-13

 

目標(biāo):實現(xiàn)反正切函數(shù)的查表算法,,精度0.5°。

分析:

f(x) = arctan(x)函數(shù)單調(diào)但非線性,越接近原點(diǎn)處,,斜率越大。

90°比較特殊,,其值為正無窮大,,只要得到的正切值tana大于114.59(89.5度對應(yīng)的正切值),就可以認(rèn)為是90度,。

假如0-89.5°用一個查找表實現(xiàn),,索引為正切值,值為角度值,。tan89.5為115,,假如用N點(diǎn)uint16_t型查找表,需要保證

arctan(115 / N) < 0.5°

即 115 / N < 0.0087

可選的最小值為13219,,意味著至少要建立一張13K×16的表,,占用26KB的Flash,對于一般的MCU來說不可接受,。

如果0-45°用一個查找表實現(xiàn),,由于tan45°=1,根據(jù)上面的計算公式,,可以得出N的最小值為114,,這個N值對一般的MCU均可以接受,,甚至可以增加至256點(diǎn)來提高精度。對于45°以上的角度,,可以根據(jù)兩角和的三角公式來得到,,推導(dǎo)過程如下:

 

arctan()函數(shù)的查表算法

如果測量的正切值K大于1,那么根據(jù)最后的公式,,可以求出比45°大的那個角度a,,再加上45°就是實際的角度。而a的計算可以由256點(diǎn)查找表來快速得到,,這樣就實現(xiàn)了用一個小容量查找表計算90度以內(nèi)的反正切值,。

查找表涉及兩個數(shù)值:表索引idx和表的角度值angle[idx]。

索引值idx對應(yīng)0-45°的正切值,,由于這些值均小于1,,采用整體擴(kuò)大256倍的方法,將正切值就映射到了0-256的區(qū)間,,從而索引idx的范圍為0-255,。

角度值angle[]是uint16_t型的,而實際的范圍為0-45,,根據(jù)65536/45=1456,,可以用Q12的表示方式來提高分辨率。

查找表如下:

static const uint16_t tb_atan[256] = {
0, 229, 458, 687, 916, 1145, 1374, 1603,
1832, 2061, 2290, 2519, 2748, 2976, 3205, 3433,
3662, 3890, 4118, 4346, 4574, 4802, 5029, 5257,
5484, 5711, 5938, 6165, 6391, 6618, 6844, 7070,
7296, 7521, 7746, 7971, 8196, 8421, 8645, 8869,
9093, 9317, 9540, 9763, 9986, 10208, 10431, 10652,
10874, 11095, 11316, 11537, 11757, 11977, 12197, 12416,
12635, 12853, 13071, 13289, 13507, 13724, 13940, 14157,
14373, 14588, 14803, 15018, 15232, 15446, 15660, 15873,
16085, 16297, 16509, 16720, 16931, 17142, 17352, 17561,
17770, 17979, 18187, 18394, 18601, 18808, 19014, 19220,
19425, 19630, 19834, 20038, 20241, 20444, 20646, 20848,
21049, 21250, 21450, 21649, 21848, 22047, 22245, 22443,
22640, 22836, 23032, 23227, 23422, 23616, 23810, 24003,
24196, 24388, 24580, 24771, 24961, 25151, 25340, 25529,
25717, 25905, 26092, 26278, 26464, 26649, 26834, 27018,
27202, 27385, 27568, 27750, 27931, 28112, 28292, 28471,
28650, 28829, 29007, 29184, 29361, 29537, 29712, 29887,
30062, 30236, 30409, 30582, 30754, 30925, 31096, 31266,
31436, 31605, 31774, 31942, 32109, 32276, 32442, 32608,
32773, 32938, 33101, 33265, 33428, 33590, 33751, 33913,
34073, 34233, 34392, 34551, 34709, 34867, 35024, 35180,
35336, 35492, 35646, 35801, 35954, 36107, 36260, 36412,
36563, 36714, 36864, 37014, 37163, 37312, 37460, 37607,
37754, 37901, 38047, 38192, 38337, 38481, 38624, 38768,
38910, 39052, 39194, 39335, 39475, 39615, 39754, 39893,
40032, 40169, 40307, 40443, 40580, 40715, 40850, 40985,
41119, 41253, 41386, 41519, 41651, 41782, 41913, 42044,
42174, 42303, 42432, 42561, 42689, 42817, 42944, 43070,
43196, 43322, 43447, 43572, 43696, 43819, 43943, 44065,
44188, 44309, 44431, 44551, 44672, 44792, 44911, 45030,
45148, 45266, 45384, 45501, 45618, 45734, 45849, 45965,
};


static int16_t calc_phase(int16_t real, int16_t imag)
{
    int16_t abs_real;
    int16_t abs_imag;
    int16_t phase;
    uint16_t zone;
    uint32_t tmp_tan;
    uint32_t delta_tan;
    if (real < 0)
    {
        abs_real = -real;
        zone = 1U;
    }
    else
    {
        abs_real = real;
        zone = 0U;
    }
    if (imag < 0)
    {
        abs_imag = -imag;
        zone += 2U;      
    }
    else
    {
        abs_imag = imag; 
        zone = 0U;       
    }
    if (abs_imag <= abs_real) 
    {
        tmp_tan = (uint32_t)abs_imag<<8U;
        tmp_tan /= abs_real;
        phase = tb_atan[tmp_tan]>>3U; 
    }
    else if ((abs_imag>>7U) <= abs_real) 
    {
        delta_tan = ((uint32_t)(abs_imag - abs_real))<<15U;
        tmp_tan = (uint32_t)abs_imag + (uint32_t)abs_real;
        delta_tan /= tmp_tan;
        delta_tan >>= 7U;
        phase = tb_atan[delta_tan]>>3U; 
        phase += 5760; 
    }
    else 
    {
        phase = 11520;
    }
    switch (zone)
    {
        case 0U:
        {
            break; 
        }
        case 1U:
        {
            phase = 23040 - phase;
            break; 
        }
        case 2U:
        {
            phase = -phase;
            break; 
        }
        case 3U:
        {
            phase = phase - 23040;
            break; 
        }
        default:
        {
            break;
        }
    }
    return(phase);
}

輔助的python計算程序如下:

#!/usr/bin/python
# -*- coding: utf-8 -*-
from math import sin
from math import cos
from math import tan
from math import atan
from math import pi
'''
#驗證FFT和相角計算的程序
wave = []
Fai = 17.5 / 180 * 3.1415926
for i in range(128):
    base = cos(3.1415926*2*i/128 + Fai)
   harm = 0.07*cos(3.1415926*11*2*i/128)
    harm = 0
    wave.append((int)(32768*(base+harm)))
# 格式化輸出
print "static const int16_t vol[128] = {"
for i in range(128):
    print "%d," %wave[i],
    if i%8 == 7:
        print
print "};"
   print "," ,round(cos(3.1415926*2*i/128),4)
'''
'''
for i in range(142,180):
    print i/2.0, tan(i * pi / 360)
'''

val_tan = []
num = 256
for i in range(num):
    val_tan.append((atan(i * 1.0 / num) * 180 / pi) )
# 格式化輸出
print "static const uint16_t arctan[%d] = {" % num
for i in range(num):
    print "%f," %val_tan[i],
    if i%8 == 7:
        print
print "};"

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多