我是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__'
答案 0 :(得分: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
您可以使用Python's slice notation代替[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]
。
实际上,由于n
是列表signal
的长度,因此您可以省略它,因为这是切片的默认行为。所以你实际上可以写:
Feven = fft(signal[::2])
Fodd = fft(signal[1::2])
在else:
子句中包含一些“else”代码并且在外部有一些代码是没有意义的。把它全部放在一个或另一个。
由于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