autopass 发表于 2015-2-10 18:21:28

三角函数近似计算(正余弦泰勒展开)


/**
* 输入角度范围为 -PI/2 到 PI/2.
* 需要5次乘法和3次加法.
*/
float _sinf(float x) {
    float x2 = x * x;
    return ( x *(1.0f -
            x2 * ((1.0f / 6) -
            x2 * ((1.0f / 120) -
            x2 *(1.0f / 5203)))));                            // 5040, 5203 可获得较高的精度.
    // return ( x *(1.0f -
            // x2 * ((1.0f / 6) -
            // x2 * ((1.0f / 120) -
            // x2 * ((1.0f / 5040) -
            // x2 *(1.0f / 362880))))));                         // 增加一级.
}

/**
*输入角度范围为 -PI/2 到 PI/2.
* 需要5次乘法和4次加法.
*/
float _cosf(float x) {
    float x2 = x * x;
    return (1.0f -
            x2 * ((1.0f / 2) -
            x2 * ((1.0f / 24) -
            x2 * ((1.0f / 720) -
            x2 *(1.0f / 41367)))));                           // 40320, 41367 可获得较高的精度.
    // return (1.0f -
            // x2 * ((1.0f / 2) -
            // x2 * ((1.0f / 24) -
            // x2 * ((1.0f / 720) -
            // x2 * ((1.0f / 40320) -
            // x2 *(1.0f / 3628800))))));                        // 增加一级.
}

/**
* 返回角度范围为 -PI 到 PI.
*/
float _atan2f(float y, float x) {
    uint8_t sx, sy;
    if(y == 0) {
      if (x >= 0) return (0);
      else      return (-PI);
    }
    if(x == 0) {
      if(y >= 0)return( PI / 2);
      else      return(-PI / 2);
    }
   
    sx = sy = 0;
    if (x < 0) {
      x = -x;
      sx = 1;
    }
    if (y < 0) {
      y = -y;
      sy = 1;
    }
   
    if (x == y) {
      y = PI / 4;
    } else {
      uint8_t mode;
      if (x > y) {
            y = y / x;
            mode = 0;
      } else {
            y = x / y;
            mode = 1;
      }
      x = y * y;
      y *= 1.0f -
             x * (0.333332062f -         // 这几个数能获得较高的精度
             x * (0.199462891f -
             x * 0.083332539f));
      if (mode != 0) {
            y = (PI / 2) - y;
      }
    }
   
    if(sx != 0) y = PI - y;
    if(sy != 0) y = -y;
   
    return (y);
}

loohoo0302 发表于 2015-2-10 20:34:28

多谢,受用了。

登云钓月 发表于 2015-2-10 23:08:40

赞。完全看不懂,不知道是否运算速度比库函数快。

bg3mo 发表于 2015-2-11 06:37:40

多谢,受用了

sangmo2015 发表于 2015-2-11 07:31:53

记得ti的dsp库给出过类似算法

moen 发表于 2015-2-11 08:34:23

思路不错            

autopass 发表于 2015-2-14 10:28:33

登云钓月 发表于 2015-2-10 23:08
赞。完全看不懂,不知道是否运算速度比库函数快。

比库函数还慢的话做近似运算就没什么意义了

NJ8888 发表于 2015-2-14 10:31:55

等有时间评估下执行速度

william_rain 发表于 2015-2-14 10:54:41

不错的{:biggrin:}{:biggrin:}

gzhuli 发表于 2015-2-14 13:07:50

精度不会很好,对于没有FPU的MCU可能也快不到哪里去。

yuyu87 发表于 2015-2-14 15:02:48

不错,收藏一下。

开放实验室小组 发表于 2015-2-14 15:29:40

泰勒展开+秦九韶算法的思想

wangyu_2011 发表于 2015-2-22 06:37:45

好东西,什么时候试试。

bj232 发表于 2015-2-22 07:01:36

没研究过算法,不知道用C支持的库函数sin,cos之类的计算,会慢多少
顺便顶楼主的分享精神,顺便补习了下大学的高等数学

NJ8888 发表于 2015-2-22 09:54:02

本帖最后由 NJ8888 于 2015-2-22 09:55 编辑

特意用STM32F100试了下,时间消耗是标准math函数中sin的1/5样子,72MHz时,_sinf调用消耗将近4.6us

mcu5i51 发表于 2015-2-22 16:34:07

受教了,虽然很少用到

autopass 发表于 2015-2-24 18:16:10

NJ8888 发表于 2015-2-22 09:54
特意用STM32F100试了下,时间消耗是标准math函数中sin的1/5样子,72MHz时,_sinf调用消耗将近4.6us ...

标准math中的sin好像是double型的,比sinf要耗时,另外标准sin/sinf的执行时间在不同的输入下有很大的差别的

sunnyqd 发表于 2015-2-24 18:55:09

5040参数一直是负的误差,5203参数的误差有正有负,总的误差5203小很多。楼主5203这个数是试出来的吗?

autopass 发表于 2015-2-25 14:55:30

sunnyqd 发表于 2015-2-24 18:55
5040参数一直是负的误差,5203参数的误差有正有负,总的误差5203小很多。楼主5203这个数是试出来的吗? ...

是试出来的,大概意思就是把余下的展开项用一个接近的常数替代.

lans0625 发表于 2015-2-25 15:23:50

试了一下,精度和运算速度都不错,谢谢楼主分享。。。。。{:handshake:}{:handshake:}

mruio 发表于 2015-2-26 21:45:42

COORDIC嘻嘻{:smile:}{:smile:}{:smile:}

默默七 发表于 2015-5-24 00:18:45

mark下,三角函数的展开算子C实现

keivenqin182 发表于 2016-2-27 13:35:05

受用多多,进一步学习,领悟三角函数

kinsno 发表于 2016-6-22 14:56:17

确实有用,我测试了一下,结果还是不错的;

闲鱼翻身 发表于 2016-6-22 15:26:46

感谢分享,MARK
页: [1]
查看完整版本: 三角函数近似计算(正余弦泰勒展开)