跟踪移动值的平方根

时间:2012-04-12 14:10:05

标签: math iteration estimation approximation sqrt

我有一个高频运行的控制回路,需要在每个周期计算一个平方根。典型的平方根函数工作正常但需要花费过多时间。由于在每个周期中取值的平方根得不到太大的值,我想找到一个迭代的平方根,它将收敛然后跟踪正确的结果。这样我就可以在每个时间步进行一次迭代,而不是很多。

问题在于,当输入发生变化时,我所见过的所有迭代平方根方法都可能会失败。特别是当输入变为零然后再次增加时,看起来会出现问题 - 这些方法并不想从零开始猜测。

我的输入范围是0-4.5,我需要大约0.01的精度,因此使用0.01的递增/递减可能需要太长时间 - 我希望它主要收敛10个周期或更少。

仅供参考我使用16 / 32bit定点输入为16bit q12。它在微控制器上,所以我对使用1K查找表不感兴趣。代码也是从simulink模型生成的,它们的表查找功能相当充满了开销。

有一个很好的解决方案吗?

4 个答案:

答案 0 :(得分:5)

0-4.5的范围相当小。精度为0.01,这只有450个可能的计算。您可以在编译时将它们全部计算为常量,并在运行时进行查找。

答案 1 :(得分:2)

如果您事先知道要处理的范围,我建议您使用查找表。生成一个数组或哈希表(取决于您正在使用的语言)到您需要的精度级别,并在需要根时参考。

答案 2 :(得分:2)

我尝试在sqrt(x)上进行二阶泰勒扩展并得到以下结果

如果y=sqrt(x),您知道y_c = sqrt(x_c)已经:

t = x-3*x_c;
y = (12*x_c*x_c-t*t)/(8*y_c*y_c*y_c);

x越大,近似越好。对于x_c=0.01x=0.02的最坏情况,结果0.1375sqrt(0.02)=0.1414的实际结果或0.0039的差异0.01 1}}。

我使用C#对代码进行了测试,并看到33%加速与Math.Sqrt()相比稳定。

答案 3 :(得分:1)

您可以使用Halley方法的一次拍摄。它具有立方收敛性,因此如果值略有变化则应该非常精确:

x_{n+1} = x_n * (x_n^2 + 3Q) / (3 x_n^2 + Q)

这会立即收敛到sqrt(Q)

参考:http://www.mathpath.org/Algor/squareroot/algor.square.root.halley.htm