1

我是 python 新手,我正在尝试 FFT 的 python 实现。我已经收到上述错误一段时间了。我该怎么办?

import numpy
import cmath

def twiddle(r,s):
    x = (cmath.exp((2*cmath.pi*1j*s)/r))
    return x


def fft(signal):
    n = len(signal)
    if n==1:
        return signal
    else:
        Feven=fft([signal[k] for k in range(0,n,2)])
        Fodd=fft([signal[k] for k in range(1,n,2)])


    for l in range (n/2):
        F1 = Feven[l] + twiddle(n, -l) * Fodd[l]
        F2 = Feven[l] - twiddle(n, -l) * Fodd[l]
        return F1+F2

当我为 Feven 和 Fodd 添加打印语句并输入以下内容时:

print (fft([4.5, 3.4, 4.7, 3.8, 6.7, 8.0, 4.6, 7.8]))

我得到:

Traceback (most recent call last):
  File "FFT.py", line 41, in <module>
    print (fft([4.5, 3.4, 4.7, 3.8, 6.7, 8.0, 4.6, 7.8]))
  File "FFT.py", line 29, in fft
    Feven=fft([signal[k] for k in range(0,n,2)])
  File "FFT.py", line 34, in fft
   F1 = Feven[l] + twiddler(n, -l) * Fodd[l]
 TypeError: 'complex' object has no attribute '__getitem__'
4

1 回答 1

5

修复错误

问题是你的线

return F1+F2

这会导致fft立即返回(使用复数F1 + F2),而实际上它应该返回一个列表。我想你的意思是这样的:

def fft(signal):
    n = len(signal)
    if n==1:
        return signal
    else:
        Feven=fft([signal[k] for k in range(0,n,2)])
        Fodd=fft([signal[k] for k in range(1,n,2)])
    F1 = [Feven[l] + twiddle(n, -l) * Fodd[l] for l in range (n/2)]
    F2 = [Feven[l] - twiddle(n, -l) * Fodd[l] for l in range (n/2)]
    return F1+F2

对您的代码的其他评论

  1. 而不是您可以使用Python 的切片表示法[signal[k] for k in range(0,n,2)]编写。同样,您可以编写.signal[0:n:2][signal[k] for k in range(1,n,2)]signal[1:n:2]

  2. 事实上,因为n是 list 的长度signal,你可以省略它,因为这是切片的默认行为。所以你实际上可以写:

    Feven = fft(signal[::2])
    Fodd = fft(signal[1::2])
    
  3. else:在子句内部和外部有一些“else”代码是没有意义的。把它放在一个或另一个。

  4. 既然Fodd数字总是乘以旋转因子,为什么不这样做一次而不是两次呢?或许是这样的:

    def fft(signal):
        n = len(signal)
        if n == 1:
            return signal
        feven = fft(signal[::2])
        fodd = [twiddle(n, -k) * o for k, o in enumerate(fft(signal[1::2]))]
        f1 = [e + o for e, o in zip(feven, fodd)]
        f2 = [e - o for e, o in zip(feven, fodd)]
        return f1 + f2
    
于 2013-05-03T09:57:23.870 回答