【问题标题】:Approximation of `atan` function in fixed point定点中`atan`函数的逼近
【发布时间】:2023-06-14 19:03:01
【问题描述】:

我必须做一些需要使用三角函数的计算,尤其是atan。代码将在 Atmega328p 上运行,为了提高效率,我不能使用 floats:我使用的是定点数。因此,我不能使用标准的atan 函数。

我有一个函数,它采用定点格式 s16_10(有符号,16 位宽度,指向第 10 位)的值,并返回 s16_6 格式。输入将介于 0 和 1 之间(因此 0 和 210),因此输出(以度为单位)将介于 -45 和 45 之间(因此 -45 * 26 和 45 * 26)。

假设Y是不动点,s16_6表示y,圆弧的实角,x如atan(x) = y,X表示x的s16_10。我从使用 4 次多项式从 (0,1) 到 (-45,45) 逼近 atan 函数开始,发现我们可以使用:

y ~= 8.11 * x^4 - 19.67 * x^3 - 0.93 * x^2 + 57.52 * x + 0.0096

这导致:

Y ~= (8.11 * X^4)/2^34 - (19.62* X^3)/2^24 - (0.93 * X^2)/2^14 + (57.52*X)/2^4 + 0.0069 * 2^6

我在这里卡住了......一方面,计算X^4 将导致定义间隔的五分之一为0,另一方面,2n4n 通常也会导致零值...我该怎么办?

【问题讨论】:

  • 最后一句可能有错别字(“另一方面,2n4 也经常导致”)-请澄清。另外,当某个中间结果为 0 时,为什么会出现问题?
  • 另外,你必须使用泰勒级数吗?有CORDIC可能更高效;我从未听说过 Atmega328p,因此无法确定哪种算法更好。
  • @anatolyg 为了清楚起见,我已经编辑了答案!这是一个问题,因为前三个成员始终为零......而且我找不到不会使变量无效的近似值。我不知道这是泰勒级数,但我会看看 CORDIC 算法
  • 您使用的是_Accum还是自定义类型?
  • 我正在使用typedef int16_t fixed16_p,其中 p 是点的位置

标签: math microcontroller trigonometry atmega approximation


【解决方案1】:

有些词被截为零不一定是灾难;这不会大大恶化您的近似值。我通过将多项式的每一项四舍五入到最接近的整数来模拟您在 Matlab 中的固定精度设置:

q4 = @(X) round((8.11 * X.^4)/2^34);
q3 = @(X) -round((19.62* X.^3)/2^24);
q2 = @(X) -round((0.93 * X.^2)/2^14);
q1 = @(X) round((57.52*X)/2^4);
q0 = @(X) round(0.0069 * 2^6);

确实,在区间 [0,210] 的前五分之一上,术语 q4、q3、q2 看起来相当不稳定,而 q4 基本上不存在。

但这些四舍五入的影响与您的多项式近似 atan 的理论误差大致相同。这是图中红色是计算出的差异(多项式-atan)没有四舍五入到整数,绿色是差异(q4+q3+q2+q1+q0-atan):

如您所见,四舍五入不会使近似值变得更糟;在大多数情况下,它实际上通过一个愉快的意外来减少错误。


我确实注意到您的多项式系统地高估了 atan。当我用 Matlab 将 4 次多项式拟合到 [0,1] 上的 atan 时,系数略有不同:

8.0927  -19.6568   -0.9257   57.5106   -0.0083

即使像您一样将这些截断为两个有效数字,我也得到了更好的近似值:

(8.09 * X^4)/2^34 - (19.66* X^3)/2^24 - (0.93 * X^2)/2^14 + (57.52*X)/2^4 - 0.0083 * 2^6

这次截断整数确实使事情变得更糟。但是可以预料,将几个中间结果四舍五入为整数的计算结果将相差 +-2 左右。该多项式显示的 +-0.5 的理论精度无法用给定的算术工具实现。

【讨论】: