Как работает numpy.fft.fft?

В настоящее время я пытаюсь понять функцию fft из numpy. Для этого я протестировал следующее предположение: У меня есть две функции: f(x) = x^2 и g(x) = f'(x) = 2*x. Согласно законам преобразования Фурье и вольфрам альфа, должно быть, что G(w) = 2pi*i*F(w) (префакторы могут меняться, но должен быть только постоянный фактор). При реализации этого в python я пишу

import numpy as np
def x2(x): return x*x
def nx(x): return 2*x
a = np.linspace(-3, 3, 16)
a1 = x2(a)
a2 = nx(a)
b1 = np.fft.fft(a1)
b2 = np.fft.fft(a2)
c = b1/b2

Теперь я ожидаю почти постоянное значение для c, но я получаю

array([ 1.02081592e+16+0.j , 1.32769987e-16-1.0054679j , 4.90653893e-17-0.48284271j, -1.28214041e-16-0.29932115j, -1.21430643e-16-0.2j , 5.63664751e-16-0.13363573j, -5.92271642e-17-0.08284271j, -4.21346622e-16-0.03978247j, -5.55111512e-16-0.j , -5.04781597e-16+0.03978247j, -6.29288619e-17+0.08284271j, 8.39500693e-16+0.13363573j, -1.21430643e-16+0.2j , -0.00000000e+00+0.29932115j, -0.00000000e+00+0.48284271j, 1.32769987e-16+1.0054679j ])

Где моя ошибка, и что я могу сделать, чтобы использовать fft, как предполагалось?

1 ответ

Приведенные свойства относятся к непрерывному преобразованию Фурье (CFT). То, что вычисляется БПФ, - это Дискретное преобразование Фурье (DFT), которое связано с ЦФТ, но не совсем эквивалентно.

Верно, что ДПФ пропорционально ЦФТ при определенных условиях: а именно с достаточной выборкой функции, которая равна нулю вне пределов выборки (см., например, Приложение E эту книгу).

Ни одно условие не выполняется для функций, которые вы предлагаете выше, поэтому DFT не пропорционален CFT, и ваши численные результаты отражают это.

Здесь некоторый код, который подтверждает через FFT отношение, которое вас интересует, используя соответствующую ограниченную по диапазону функцию:

import numpy as np
def f(x): return np.exp(-x ** 2)
def fprime(x): return -2 * x * f(x)
a = np.linspace(-10, 10, 100)
a1 = f(a)
a2 = fprime(a)
b1 = np.fft.fft(a1)
b2 = np.fft.fft(a2)
omega = 2 * np.pi * np.fft.fftfreq(len(a), a[1] - a[0])
np.allclose(b1 * 1j * omega, b2)
# True

licensed under cc by-sa 3.0 with attribution.