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