我正在写一个简单的傅里叶变换实现,并查看了维基百科上的 DFT 方程以供参考,当我注意到我在做一些不同的事情时,经过思考后觉得维基百科的版本一定是错误的,因为它很容易想到一个信号表明,当傅立叶变换(使用该等式)将返回不正确的频谱:因为该等式仅将信号围绕复平面包裹一次(由于的),任何周期性的信号偶数次(在包裹复平面时)将没有频谱,因为在 DFT 期间出现的通常峰值(在围绕单位圆时)将相互抵消(当它们出现偶数时)。
为了检查这一点,我编写了一些生成以下图像的代码,这似乎证实了我的想法。
“时间使用方程”使用方程 与向量时间(例如采样的它可以在下面的函数中找到。
ft
上面链接的维基百科方程在这里复制以供参考: 可以在函数中找到。
ft2
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
def ft(t, s, fs):
freq_step = fs / len(s)
freqs = np.arange(0, fs/2 + freq_step, freq_step)
S = []
for freq in freqs:
real = np.sum(s * np.cos(2*np.pi*freq * t))
compl = np.sum(- s * np.sin(2*np.pi*freq * t))
tmpsum = (real**2 + compl**2) ** 0.5
S.append(tmpsum)
return S, freqs
def ft2(s, fs): # Using wikipedia equation
nump=len(s)
freq_step = fs / nump
freqs = np.arange(0, fs/2 + freq_step, freq_step)
S = []
for i, freq in enumerate(freqs):
real = np.sum(s * np.cos(2*np.pi*freq * i/nump))
compl = np.sum(- s * np.sin(2*np.pi*freq * i/nump))
tmpsum = (real**2 + compl**2) ** 0.5
S.append(tmpsum)
return S, freqs
def main():
f = 5
fs = 100
t = np.linspace(0, 2, 200)
y = np.sin(2*np.pi*f*t) + np.cos(2*np.pi*f*2*t)
fig = plt.figure()
ax = fig.add_subplot(311)
ax.set_title('Signal in time domain')
ax.set_xlabel('t')
ax.plot(t, y)
S, freqs = ft(t, y, fs)
ax = fig.add_subplot(312)
ax.set_xticks(np.arange(0, freqs[-1], 2))
ax.set_title('Time using equation')
ax.set_xlabel('frequency')
ax.plot(freqs, S)
S, freqs = ft2(y, fs)
ax = fig.add_subplot(313)
ax.set_title('Using Wiki equation')
ax.set_xlabel('frequency')
ax.set_xticks(np.arange(0, freqs[-1], 2))
ax.plot(freqs, S)
plt.tight_layout()
plt.show()
main()
显然,我似乎不太可能在如此高调的 wiki 页面上随机发现错误。但我看不出我所做的有什么错误?