为什么不使用Scipy的FFT代码结果与Scipy FFT不一样?

Ngu*_*Duy 4 python numpy fft matplotlib scipy

下面的FFT代码没有得到类似于scipyPython库的结果。但是我不知道这段代码有什么问题。

import numpy as np
import matplotlib.pyplot as plt
#from scipy.fftpack import fft

def omega(p, q):
   return np.exp((-2j * np.pi * p) / q)

def fft(x):
   N = len(x)
   if N <= 1: return x
   even = fft(x[0::2])
   odd = fft(x[1::2])
   combined = [0] * N
   for k in range(N//2):
     combined[k] = even[k] + omega(k,N) * odd[k]
     combined[k + N//2] = even[k] - omega(k,N) * odd[k]
   return combined

 N = 600
 T = 1.0 / 800.0
 x = np.linspace(0, N*T, N)
 #y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
 y = np.sin(50.0 * 2.0*np.pi*x)
 xf = np.linspace(0.0, 1.0/(2.0*T), N//2)
 yf = fft(y)
 yfa = 2.0/N * np.abs(yf[0:N//2])
 plt.plot(xf, yfa)
 plt.show()
Run Code Online (Sandbox Code Playgroud)

这给出:

FFT图

Yac*_*ola 5

以上所有注释,四舍五入错误和实现正确性,都是正确的,但您错过了重要的事情... FFT Cooley和Tukey原始算法仅在样本数N为2的幂时才起作用。

N600

np.allclose(yfa,yfa_sp)
>>> False
Run Code Online (Sandbox Code Playgroud)

对于您当前的输入N = 600,输出与numpy / scipy之间的差异非常大。但是现在,让我们使用2的幂,在这种情况下N = 2**9 = 512

np.allclose(yfa,yfa_sp)
>>> True
Run Code Online (Sandbox Code Playgroud)

太棒了:这次的输出是相同的,您可以针对输入信号2的其他幂次幂(相距奈奎斯特准则)进行验证y。对于深入的解释,您可以阅读该问题的公认答案,以了解为什么numpy / scipy fft函数可以允许全部N(效率最高时N为2的幂,最低效率时N为素数),而不是像您那样处理此异常应该有这样的东西:

if np.log2(N) % 1 > 0:
    raise ValueError('size of input y must be a power of 2') 
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。