5

我正在上的8位微控制器(HCS08)的乐趣实现在组件中的FFT算法2个平方和的平方根。一旦算法完成,我就会有8位实/虚对的数组,我想找到这些值的大小。也就是说,如果X是复杂的,我想找到逼近微控制器上

|x| = sqrt(Re{x}^2 + Im{x}^2) 

现在我提供给我一个16位寄存器和一个8位寄存器。我想到刚现蕾他们,加入他们,并取结果的平方根,但这带来了一个问题:两个8位数字的平方和的最大可能值为〜130K,比大一个16位寄存器可以保持最大值(65.5k)。

我想出了一个子程序,它计算一个16位数的整数平方根,这看起来工作得很好,但显然我不能保证使用适合16位的值。我的想法现在的问题是,有一个算法,将大致与我直接的需要,但我似乎无法找到任何东西。任何想法将不胜感激。

总结:说我有2个8位分量的向量,我想找到向量的长度。我怎么能近似这个而不用真正计算正方形和平方根呢?

谢谢!

+1

可以使用CORDIC算法(http://en.wikipedia.org/wiki/CORDIC)将矢量“”旋转到某个新矢量“”(或等价ale然'<0,y1>'。 'x1'(或'y1')给出了原始向量的大小,CORDIC可以在不乘法的情况下实现。虽然我从来没有做过,但也不知道它有多难。 – mtrw 2011-04-03 06:38:58

+0

这是否适用于音频?你会在之后计算log10,以获得dB值吗? – 2011-04-03 08:13:14

+0

取决于目的:如果你需要长度,那么就没有其他方法可以计算,但是当你需要规范(通常是长度)时,你可以使用另一个规范而不是默认的L2规范,即例如曼哈顿距离(= | real | + | imag |)。 – flolo 2011-04-03 09:52:53

回答

3

如果总和大于65535,则将其除以4(右移2位),取平方根并乘以2.您将失去一位准确性,并且自然结果不能保证以适应8位。

+0

感谢您的回应。我唯一担心的是如果总和大于65535,它会溢出,我无法知道。 (我只有一个16位寄存器,因此添加两个16位数可能会产生不可预知的结果。)我认为我可以通过将Re {x}和Im {x}除以2来完成相同的操作,然后将最终的回答2;这听起来相当于你的建议吗? – user599599 2011-04-03 05:48:10

+0

是的,你的想法会起作用,并给出预期的精度。 – swestrup 2011-04-03 11:35:47

+0

你已经接受了这个答案,所以我猜你已经想通了:将输入除以4,并将输出乘以2. – 2011-04-04 03:16:03

0

好了,你可以在极坐标形式写X:

x = r[cos(w) + i sin(w)] 

其中w = arctan(Im(x)/Re(x)),所以

|x| = r = Re(x)/cos(w) 

这里没有大的数字,但也许你会失去三角函数精度(即, if您可以访问三角函数: - /)

+0

嗯,有趣的想法。不幸的是,我不能访问trig函数,无论如何也没有浮点支持,所以我基本上只限于基本的整数运算。不过,我计划有一个trig查找表,所以我会牢记这一点。 – user599599 2011-04-03 06:25:47

6

有一个网页描述Fast Magnitude Estimator 。基本思想是获得等式的最小二乘方(或其他高质量):

Mag ~= Alpha * max(|I|, |Q|) + Beta * min(|I|, |Q|) 

为系数Alpha和Beta。列出了几个系数对,其中包括均方误差,最大误差等,包括适用于整数ALU的系数。

+0

看起来像61/64的选择之一将是对这个应用程序很好。 – 2011-04-04 03:21:06

0

,可能会或可能不适合一个廉价的和脏的方法是使用

|x| ~ max(|Re{x}|,|Im{x}|) + min(|Re{x}|,|Im{x})/2; 

这将趋向于过高估计| X |介于0到12%之间。

0

如果你打算随后的量级来转换为分贝,那么你就免去了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 
+0

好点,但我的问题是,log10也是一个计算昂贵的操作。我仍然有找到最接近的整数或使用查找表的问题。 – user599599 2011-04-09 23:12:14

+0

@ user599599:是的,你仍然有'log',但以前你有'sqrt' +'log',现在你只有'​​log'。 – 2011-04-10 18:23:47