我有以下代码...请注意#下的两行生成正弦曲线。一个使用2pi的精度要比另一个使用更高的精度,尽管如此,它们仍应给出几乎相同的结果。
import numpy as np
import matplotlib.pyplot as plt
t1 = np.arange(0., 1., .01)
# generate sine curve
y1 = np.sin(6.28318*5.*t1)
#y1 = np.sin(6.283185307179586*5.*t1) # equivalent to np.sin(2*np.pi*t1)
# calculate the fft (no averaging!) of the time series
ffty = np.fft.fft(y1)
fig, ax_list = plt.subplots(3,1)
ax_list[0].plot(t1,y1, '.-')
ax_list[1].plot(ffty.real, '.-', label='Real Part')
ax_list[1].legend()
ax_list[2].plot(ffty.imag, '.-', label='Imag Part')
ax_list[2].legend()
plt.show()
如果以较低的精度6.28318运行代码,则会得到fft的预期结果...
但是,如果您以较高的精度6.283185307179586(等于2. * numpy.pi)运行代码,则会在下面得到意外的结果...实际部分完全错误...振幅相差甚远,它不是对称的,没有任何意义。
我不知道是什么原因造成的。有人有什么想法吗?
答案 0 :(得分:5)
这是完全预期的行为。计算机使用浮点计算,这本来就不精确。
请注意实际结果的y轴。如果不存在数值误差,则实数部分将等于0。使用“更高的精度”结果,实数部分几乎等于0(1e-14非常接近于双精度浮点数的精度)。精度较低时,实部会变得更大(尽管比虚部还大得多,小得多)。由于数量较大,因此结构也更多(即错误不是由舍入误差引起的,而是由输入数据的实际特征决定的,周期短于理想值)。
答案 1 :(得分:4)
正如@Cris Luengo所说,您需要查看y轴的比例才能准确比较两个图。进行此操作的另一种方法是,将要尝试比较的所有内容都绘制在同一图上,如下所示。
使用对数标度来显示FFT的大小,并且很明显,使用pi的较少有效数字确实会导致精度降低。 正如使用浮点数时所预期的那样,大多数值并不完全为零,但是使用更高的有效数字可以使幅度提高许多数量级,当分别绘制FFT时,这并不能立即看出。
使用的代码:
import numpy as np
import matplotlib.pyplot as plt
t1 = np.arange(0., 1., .01)
values = {
'low':6.28318,
'higher':6.283185307179586,
'highest':2*numpy.pi,
}
styles = {
'low':'-',
'higher':'-',
'highest':'.-'
}
fig, ax_list = plt.subplots(3,1)
for name, tau in values.items():
y1 = np.sin(tau*5.*t1)
ffty = np.fft.fft(y1)
ax_list[0].plot(t1,y1, styles[name], label=name)
ax_list[1].plot(abs(ffty.real), styles[name],label=name)
ax_list[2].plot(abs(ffty.imag), styles[name], label=name)
[ax.legend() for ax in ax_list]
ax_list[0].set_title('time domain')
ax_list[1].set_title('real part')
ax_list[2].set_title('imaginary part')
ax_list[1].set_yscale('log')
ax_list[2].set_yscale('log')
plt.draw()