为什么不使用 Scipy 的 FFT 代码的结果与 Scipy FFT 不相似?
Why is the result in FFT code without using Scipy not similar to Scipy FFT?
下面的 FFT 代码没有给出类似于 Python 的 scipy
库的结果。但是我不知道这段代码有什么问题。
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()
这给出:
以上所有评论,即 舍入错误和实现的正确性,都是正确的,但你错过了一件重要的事情......FFT Cooley 和 Tukey 原始算法仅在数字时有效样本数 N
是 2 的幂。您确实注意到
np.allclose(yfa,yfa_sp)
>>> False
对于您当前的输入 N = 600
,您的输出与 numpy/scipy 之间的差异很大。但是现在,让我们使用 2 的幂,在本例中为 N = 2**9 = 512
,它给出
np.allclose(yfa,yfa_sp)
>>> True
太棒了!这次输出是相同的,并且可以验证输入信号大小的其他 2 次方(除了奈奎斯特准则)y
。对于深入的解释,您可以阅读 this question 的公认答案以了解为什么 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')
正如评论中所建议的,如果不能如此轻易地修改信号的大小,零填充绝对是解决此类采样问题的方法。
希望对您有所帮助。
下面的 FFT 代码没有给出类似于 Python 的 scipy
库的结果。但是我不知道这段代码有什么问题。
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()
这给出:
以上所有评论,即 舍入错误和实现的正确性,都是正确的,但你错过了一件重要的事情......FFT Cooley 和 Tukey 原始算法仅在数字时有效样本数 N
是 2 的幂。您确实注意到
np.allclose(yfa,yfa_sp)
>>> False
对于您当前的输入 N = 600
,您的输出与 numpy/scipy 之间的差异很大。但是现在,让我们使用 2 的幂,在本例中为 N = 2**9 = 512
,它给出
np.allclose(yfa,yfa_sp)
>>> True
太棒了!这次输出是相同的,并且可以验证输入信号大小的其他 2 次方(除了奈奎斯特准则)y
。对于深入的解释,您可以阅读 this question 的公认答案以了解为什么 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')
正如评论中所建议的,如果不能如此轻易地修改信号的大小,零填充绝对是解决此类采样问题的方法。
希望对您有所帮助。