我正在努力在8位微控制器(HCS08)上组装FFT算法。一旦算法完成,我将有一个8位实/虚对的数组,我想找到每个值的大小。也就是说,如果 x 很复杂,我想找到
|x| = sqrt(Re{x}^2 + Im{x}^2)
现在我可以使用16位寄存器和8位寄存器。我想到只是对它们进行平方,添加它们,并取结果的平方根,但这会产生一个问题:两个8位数的平方和的最大可能值为~130k,大于16位寄存器可以容纳的最大值(65.5k)。
我想出了一个子程序,它计算一个16位数的整数平方根,这似乎运行良好,但显然我不能保证使用适合16位的值。我现在的想法是,有一种算法能够直接逼近我需要的算法,但我似乎找不到任何东西。任何想法将不胜感激。
总结一下:假设我有一个带有两个8位分量的向量,我想找到向量的长度。如何在不实际计算平方和平方根的情况下对其进行近似计算?
谢谢!
答案 0 :(得分:6)
有一个描述Fast Magnitude Estimator的网页。基本思想是使方程符合最小二乘(或其他高质量):
Mag ~= Alpha * max(|I|, |Q|) + Beta * min(|I|, |Q|)
表示系数Alpha和Beta。列出了几个系数对,其中包括均方误差,最大误差等,包括适用于整数ALU的系数。
答案 1 :(得分:3)
如果总和大于65535,则将其除以4(右移2位),取平方根,然后乘以2.您将失去一位精度,当然结果不能保证适合8位。
答案 2 :(得分:0)
好吧,你可以写极性形式的x:
x = r[cos(w) + i sin(w)]
其中w = arctan(Im(x)/Re(x))
,所以
|x| = r = Re(x)/cos(w)
这里没有大数字,但也许你会失去三角函数的精确度(也就是说,如果你可以访问三角函数: - /)
答案 3 :(得分:0)
一种廉价而肮脏的方法,可能适用也可能不适合使用
|x| ~ max(|Re{x}|,|Im{x}|) + min(|Re{x}|,|Im{x})/2;
这往往会高估| x |在0到12%之间。
答案 4 :(得分:0)
如果您随后要将幅度转换为dB,那么您将完全取消sqrt
操作。即如果你的计算是:
magnitude = sqrt(re*re+im*im); // calculate magnitude of complex FFT output value
magnitude_dB = 20*log10(magnitude); // convert magnitude to dB
您可以将其重写为:
magnitude_sq = re*re+im*im; // calculate squared magnitude of complex FFT output value
magnitude_dB = 10*log10(magnitude_sq); // convert squared magnitude to dB
答案 5 :(得分:0)
您可能只受限于2个寄存器,但您可以在http://www.realitypixels.com/turk/opensource/index.html查看此代码 固定点平方根 使用CORDIC的定点三角函数