我必须做一些需要使用三角函数的计算,尤其是atan
函数。代码将在Atmega328p上运行,为了提高效率,我无法使用float
:我使用定点数。因此,我无法使用标准的atan
函数。
具有以定点格式s16_10(带符号,16位宽度,第10位的点)取值的函数,并返回s16_6格式。输入将介于0和1之间(因此0和2 10 ),因此输出(以度为单位)将介于-45和45之间(所以-45 * 2 6 和45 * 2 6 )。
让我们说Y是固定点,y是s16_6表示,弧的实际角度,x是atan(x) = y
,X是x16的s16_10表示。我首先用{4}多项式近似atan
函数,从(0,1)到(-45,45),发现我们可以使用:
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,另一方面为2 n4 {3,2,1} 中的 n通常也会导致零值...我该怎么办?
答案 0 :(得分:5)
一些被截断为零的术语不一定是灾难;这并没有大大恶化你的近似值。我通过将多项式的每个项舍入到最接近的整数来模拟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,2 10 ]中,术语q4,q3,q2看起来相当不稳定,而q4基本上不存在。
但这些舍入的效果与你的多项式近似atan
的理论误差大小相同。下面的图是红色是差值(多项式 - atan)计算没有舍入到整数,绿色是差值(q4 + q3 + q2 + q1 + q0-atan):
正如您所看到的,舍入不会使逼近变得更糟;在大多数情况下,它实际上通过一次快乐事故减少了错误。
我注意到你的多项式系统地过高估计了atan。当我用Matlab将4次多项式拟合到[0,1]时,系数略有不同:
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的理论精度不能用给定的算术工具来实现。