周期\(2\pi\)の関数を等間隔で\(N\)分割してそれぞれのサンプル点を
$$ \theta_l = \frac{2\pi}{N}, (l = 0, 1, 2 … N-1) $$
、サンプル点での値を\(f_l\)とすると、離散フーリエ変換の係数は
$$ F_k = \frac{1}{N} \sum_{l=0}^{N-1} f_l e^{-i2\pi kl/N} $$
となる。
複素表示を展開すると
$$ \begin{align*} F_k &= \frac{1}{N} \sum_{l=0}^{N-1} f_l e^{-i2\pi kl/N} \\ &= \frac{1}{N} \sum_{l=0}^{N-1} \left\lbrace f_l \left( \cos(-2\pi kl/N) + i \sin(-2\pi kl/N) \right) \right\rbrace \\ &= \frac{1}{N} \sum_{l=0}^{N-1} \left\lbrace f_l \left( \cos(2\pi kl/N) - i \sin(2\pi kl/N) \right) \right\rbrace \\ &= \frac{1}{N} \sum_{l=0}^{N-1} f_l \cos(2\pi kl/N) - i\frac{1}{N} \sum_{l=0}^{N-1} f_l \sin(2\pi kl/N) \\ \end{align*} $$
となる。
逆変換
サンプル点を復元する逆変換は、
$$ \begin{align*} f_l &= \sum_{k=0}^{N-1} F_k e^{i2\pi kl/N} \\ &= \sum_{k=0}^{N-1} (Fr_k + i Fi_k) (\cos(2\pi kl/N) + i\sin(2\pi kl/N)) \\ &= \sum_{k=0}^{N-1} (Fr_k \cos(2\pi kl/N) - Fi_k \sin(2\pi kl/N)) + i \sum_{k=0}^{N-1} (Fr_k \sin(2\pi kl/N) + Fi_k \cos(2\pi kl/N)) \\ \end{align*} $$
プログラム化
Rubyの配列にベクトル演算を仕込む:
class Array |
離散フーリエ変換を行うクラス:
|
sin, cosを作るヘルパー関数
def make_cos_tbl(n, k) |
テスト:
dft8 = DFT.new(8) |
結果:
[1, 7, 3, 2, 0, 5, 0, 8] # 元のベクトル |
- 計算量はO(N^2)