f [ k ] = ∑ n = 0 N − 1 g [ n ] e − i ( 2 π / N ) k n , 其中 ( 0 < = n < N ) f[k]=\sum_{n=0}^{N-1}g[n]e^{-i(2\pi/N)kn}, 其中(0<=n
g [ n ] = 1 N ∑ k = 0 N − 1 f [ k ] e i ( 2 π / N ) k n , 其中 ( 0 < = k < N ) g[n]=\frac{1}{N}\sum_{k=0}^{N-1}f[k]e^{i(2\pi/N)kn}, 其中(0<=k
从以上公式看,如果直接按照公式来求离散傅里叶变换,其时间复杂度是O(N^2)
快速傅里叶变换就是一种能在O(n*log(n))时间复杂度内进行傅里叶变换及其逆变换的算法
令
G = [ g [ 0 ] g [ 1 ] ⋮ g [ n − 1 ] ] F = [ f [ 0 ] f [ 1 ] ⋮ f [ n − 1 ] ] G= \begin{bmatrix} g[0] \\ g[1] \\ \vdots \\ g[n-1] \end{bmatrix} \\\ \\\ F= \begin{bmatrix} f[0] \\ f[1] \\ \vdots \\ f[n-1] \end{bmatrix} \\\ G= g[0]g[1]⋮g[n−1] F= f[0]f[1]⋮f[n−1]
E [ i ] = [ e − i ( 2 π / N ) ∗ 0 ∗ 0 e − i ( 2 π / N ) ∗ 0 ∗ 1 ⋯ e − i ( 2 π / N ) ∗ 0 ∗ ( n − 1 ) e − i ( 2 π / N ) ∗ 1 ∗ 0 95 ⋯ e − i ( 2 π / N ) ∗ 1 ∗ ( n − 1 ) ⋮ ⋮ ⋱ ⋱ ⋮ ⋮ ⋱ e − i ( 2 π / N ) ∗ ( n − 1 ) ∗ ( n − 1 ) ] E[i]=\begin{bmatrix} e^{-i(2\pi/N)*0*0} & e^{-i(2\pi/N)*0*1} & \cdots & e^{-i(2\pi/N)*0*(n-1)} \\ e^{-i(2\pi/N)*1*0} & 95 & \cdots & e^{-i(2\pi/N)*1*(n-1)} \\ \vdots & \vdots & \ddots & \ddots \\ \vdots & \vdots & \ddots & e^{-i(2\pi/N)*(n-1)*(n-1)} \\ \end{bmatrix} E[i]= e−i(2π/N)∗0∗0e−i(2π/N)∗1∗0⋮⋮e−i(2π/N)∗0∗195⋮⋮⋯⋯⋱⋱e−i(2π/N)∗0∗(n−1)e−i(2π/N)∗1∗(n−1)⋱e−i(2π/N)∗(n−1)∗(n−1)
则离散傅里叶公式可改写为
F = E [ i ] ∗ G F=E[i]*G F=E[i]∗G
逆变换可改写为
G = 1 N E [ − i ] ∗ F G=\frac{1}{N}E[-i]*F G=N1E[−i]∗F
注意: E[i]里的 i 是一个变量,i 即正虚数单位,代表正变换,-i 代表逆变换,下同。
令
E [ i ] [ n ] = [ e − i ( 2 π / N ) ∗ k ∗ 0 e − i ( 2 π / N ) ∗ k ∗ 1 … e − i ( 2 π / N ) ∗ k ∗ ( n − 1 ) ] E [ i ] [ n ] 0 n = [ e − i ( 2 π / N ) ∗ k ∗ 0 e − i ( 2 π / N ) ∗ k ∗ 2 … e − i ( 2 π / N ) ∗ k ∗ ( n − 2 ) ] E [ i ] [ n ] 1 n = [ e − i ( 2 π / N ) ∗ k ∗ 1 e − i ( 2 π / N ) ∗ k ∗ 3 … e − i ( 2 π / N ) ∗ k ∗ ( n − 1 ) ] E[i][n]=\begin{bmatrix} e^{-i(2\pi/N)*k*0} & e^{-i(2\pi/N)*k*1} & \dots & e^{-i(2\pi/N)*k*(n-1)}\\ \end{bmatrix} \\\ \\\ E[i][n]^{0n}=\begin{bmatrix} e^{-i(2\pi/N)*k*0} & e^{-i(2\pi/N)*k*2} & \dots & e^{-i(2\pi/N)*k*(n-2)}\\ \end{bmatrix} \\\ \\\ E[i][n]^{1n}=\begin{bmatrix} e^{-i(2\pi/N)*k*1} & e^{-i(2\pi/N)*k*3} & \dots & e^{-i(2\pi/N)*k*(n-1)}\\ \end{bmatrix} \\ E[i][n]=[e−i(2π/N)∗k∗0e−i(2π/N)∗k∗1…e−i(2π/N)∗k∗(n−1)] E[i][n]0n=[e−i(2π/N)∗k∗0e−i(2π/N)∗k∗2…e−i(2π/N)∗k∗(n−2)] E[i][n]1n=[e−i(2π/N)∗k∗1e−i(2π/N)∗k∗3…e−i(2π/N)∗k∗(n−1)]
则
E [ i ] = [ E [ 0 ] [ n ] 0 n E [ 0 ] [ n ] 1 n ⋮ ⋮ E [ n − 1 ] [ n ] 0 n E [ n − 1 ] [ n ] 1 n ] \\ E[i]= \begin{bmatrix} E[0][n]^{0n} & E[0][n]^{1n} \\ \vdots & \vdots \\ E[n-1][n]^{0n} & E[n-1][n]^{1n} \\ \end{bmatrix} \\ E[i]= E[0][n]0n⋮E[n−1][n]0nE[0][n]1n⋮E[n−1][n]1n
将E[i]矩阵竖着再切一刀,平分两半,用数学语言描述就是,
令
E 00 ( n / 2 ) = [ E [ 0 ] [ n ] 0 n ⋮ E [ n / 2 − 1 ] [ n ] 0 n ] E 01 ( n / 2 ) = [ E [ 0 ] [ n ] 1 n ⋮ E [ n / 2 − 1 ] [ n ] 1 n ] E 10 ( n / 2 ) = [ E [ n / 2 ] [ n ] 0 n ⋮ E [ n − 1 ] [ n ] 0 n ] E 11 ( n / 2 ) = [ E [ n / 2 ] [ n ] 1 n ⋮ E [ n − 1 ] [ n ] 1 n ] \\ E_{00(n/2)}= \begin{bmatrix} E[0][n]^{0n} \\ \vdots \\ E[n/2-1][n]^{0n}\\ \end{bmatrix} \\\ \\\ E_{01(n/2)}= \begin{bmatrix} E[0][n]^{1n} \\ \vdots \\ E[n/2-1][n]^{1n}\\ \end{bmatrix} \\\ \\\ E_{10(n/2)}= \begin{bmatrix} E[n/2][n]^{0n} \\ \vdots \\ E[n-1][n]^{0n}\\ \end{bmatrix} \\\ \\\ E_{11(n/2)}= \begin{bmatrix} E[n/2][n]^{1n} \\ \vdots \\ E[n-1][n]^{1n}\\ \end{bmatrix} \\\\ E00(n/2)= E[0][n]0n⋮E[n/2−1][n]0n E01(n/2)= E[0][n]1n⋮E[n/2−1][n]1n E10(n/2)= E[n/2][n]0n⋮E[n−1][n]0n E11(n/2)= E[n/2][n]1n⋮E[n−1][n]1n
于是
E [ i ] = [ E 00 ( n / 2 ) E 01 ( n / 2 ) E 10 ( n / 2 ) E 11 ( n / 2 ) ] E[i]=\begin{bmatrix} E_{00(n/2)} & E_{01(n/2)} \\ E_{10(n/2)} & E_{11(n/2)} \\ \end{bmatrix} E[i]=[E00(n/2)E10(n/2)E01(n/2)E11(n/2)]
再令
w [ k ] = e − i ( 2 π / N ) ∗ k w[k]=e^{-i(2\pi/N)*k} w[k]=e−i(2π/N)∗k
W 0 ( n / 2 ) = [ w [ 0 ] 0 0 … 0 0 w [ 1 ] 0 … 0 0 0 w [ 2 ] … 0 ⋮ ⋮ ⋮ ⋮ 0 0 0 0 … w [ n / 2 − 1 ] ] W 1 ( n / 2 ) = [ w [ n / 2 ] 0 0 … 0 0 w [ n / 2 + 1 ] 0 … 0 0 0 w [ n / 2 + 2 ] … 0 ⋮ ⋮ ⋮ ⋮ 0 0 0 0 … w [ n − 1 ] ] W^{0(n/2)}=\begin{bmatrix} w[0] & 0 & 0 & \dots & 0 \\ 0 & w[1] & 0 & \dots & 0 \\ 0 & 0 & w[2] & \dots & 0 \\ \vdots & \vdots & \vdots & \vdots & 0 \\ 0 & 0 & 0 & \dots & w[n/2-1] \\ \end{bmatrix} \\\ \\\ W^{1(n/2)}=\begin{bmatrix} w[n/2] & 0 & 0 & \dots & 0 \\ 0 & w[n/2+1] & 0 & \dots & 0 \\ 0 & 0 & w[n/2+2] & \dots & 0 \\ \vdots & \vdots & \vdots & \vdots & 0 \\ 0 & 0 & 0 & \dots & w[n-1] \\ \end{bmatrix} W0(n/2)= w[0]00⋮00w[1]0⋮000w[2]⋮0………⋮…0000w[n/2−1] W1(n/2)= w[n/2]00⋮00w[n/2+1]0⋮000w[n/2+2]⋮0………⋮…0000w[n−1]
于是
E [ i ] = [ E 00 ( n / 2 ) E 01 ( n / 2 ) E 10 ( n / 2 ) E 11 ( n / 2 ) ] = [ E 00 ( n / 2 ) W 0 ( n / 2 ) ∗ E 00 ( n / 2 ) E 10 ( n / 2 ) W 1 ( n / 2 ) ∗ E 10 ( n / 2 ) ] = [ E 00 ( n / 2 ) W 0 ( n / 2 ) ∗ E 00 ( n / 2 ) − E 00 ( n / 2 ) − W 1 ( n / 2 ) ∗ E 00 ( n / 2 ) ] = [ E 00 ( n / 2 ) W 0 ( n / 2 ) ∗ E 00 ( n / 2 ) − E 00 ( n / 2 ) W 0 ( n / 2 ) ∗ E 00 ( n / 2 ) ] E[i] =\begin{bmatrix} E_{00(n/2)} & E_{01(n/2)} \\ E_{10(n/2)} & E_{11(n/2)} \\ \end{bmatrix} \\\ \\\ =\begin{bmatrix} E_{00(n/2)} & W^{0(n/2)}*E_{00(n/2)} \\ E_{10(n/2)} & W^{1(n/2)}*E_{10(n/2)} \\ \end{bmatrix} \\\ \\\ =\begin{bmatrix} E_{00(n/2)} & W^{0(n/2)}*E_{00(n/2)} \\ -E_{00(n/2)} & -W^{1(n/2)}*E_{00(n/2)} \\ \end{bmatrix} \\\ \\\ =\begin{bmatrix} E_{00(n/2)} & W^{0(n/2)}*E_{00(n/2)} \\ -E_{00(n/2)} & W^{0(n/2)}*E_{00(n/2)} \\ \end{bmatrix} E[i]=[E00(n/2)E10(n/2)E01(n/2)E11(n/2)] =[E00(n/2)E10(n/2)W0(n/2)∗E00(n/2)W1(n/2)∗E10(n/2)] =[E00(n/2)−E00(n/2)W0(n/2)∗E00(n/2)−W1(n/2)∗E00(n/2)] =[E00(n/2)−E00(n/2)W0(n/2)∗E00(n/2)W0(n/2)∗E00(n/2)]
上面这一步就是整个转化的核心了。
再往后,令
G 0 ( n / 2 ) = [ g [ 0 ] g [ 2 ] ⋮ g [ n − 2 ] ] G 1 ( n / 2 ) = [ g [ 1 ] g [ 3 ] ⋮ g [ n − 1 ] ] G^{0(n/2)}= \begin{bmatrix} g[0] \\ g[2] \\ \vdots \\ g[n-2] \end{bmatrix} \\\ \\\ G^{1(n/2)}= \begin{bmatrix} g[1] \\ g[3] \\ \vdots \\ g[n-1] \end{bmatrix} \\\ G0(n/2)= g[0]g[2]⋮g[n−2] G1(n/2)= g[1]g[3]⋮g[n−1]
则
F = G E [ i ] F = [ E 00 ( n / 2 ) W 0 ( n / 2 ) ∗ E 00 ( n / 2 ) − E 00 ( n / 2 ) W 0 ( n / 2 ) ∗ E 00 ( n / 2 ) ] ∗ [ G 0 ( n / 2 ) G 1 ( n / 2 ) ] F=GE[i] \\\ F = \begin{bmatrix} E_{00(n/2)} & W^{0(n/2)}*E_{00(n/2)} \\ -E_{00(n/2)} & W^{0(n/2)}*E_{00(n/2)} \\ \end{bmatrix} * \begin{bmatrix} G^{0(n/2)} \\ G^{1(n/2)} \\ \end{bmatrix} \\ \\\\ F=GE[i] F=[E00(n/2)−E00(n/2)W0(n/2)∗E00(n/2)W0(n/2)∗E00(n/2)]∗[G0(n/2)G1(n/2)]
到这一步,可以看到,我们已经成功将一个 n 阶的离散傅里叶变换降为了 n/2 阶,到这里就实现了O(n*logn)时间复杂度的快速傅里叶算法。
逆变换的和正变换的大同小异,就不在赘述了。
如果想要更简洁的形式,更深刻的理解离散傅里叶变换,可以进一步化简。
令
M = E 00 ( n / 2 ) ∗ G 0 ( n / 2 ) N = E 00 ( n / 2 ) ∗ G 1 ( n / 2 ) Z = W 0 ( n / 2 ) M=E_{00(n/2)}*G^{0(n/2)} \\\\ N=E_{00(n/2)}*G^{1(n/2)} \\\\ Z=W^{0(n/2)} \\\\ M=E00(n/2)∗G0(n/2)N=E00(n/2)∗G1(n/2)Z=W0(n/2)
则
F = [ M + Z ∗ N − M + Z ∗ N ] F = \begin{bmatrix} M+Z*N \\ -M+Z*N \\ \end{bmatrix} F=[M+Z∗N−M+Z∗N]
public class FFT {
/**
* 傅里叶变换
* @param x
* @return
*/
public static Complex[] fft(Complex[] x){
return fftTrans(x, true);
}
/**
* 逆傅里叶变换
* @param x
* @return
*/
public static Complex[] ifft(Complex[] x) {
int N = x.length;
Complex[] y = fftTrans(x, false);
for (int n = 0; n < N; n++) {
y[n] = y[n].divides(N);
}
return y;
}
public static Complex[] fftTrans(Complex[] x, boolean dire) {
int N = x.length;
Complex[] y = new Complex[N];
if (N == 1) {
y[0] = x[0];
return y;
}
Complex[] x0 = new Complex[N/2];
for (int n = 0; n < N; n += 2) {
x0[n/2] = x[n];
}
Complex[] X0 = fftTrans(x0, dire);
Complex[] x1 = new Complex[N/2];
for (int n = 1; n < N; n += 2) {
x1[n/2] = x[n];
}
Complex[] X1 = fftTrans(x1, dire);
for (int k = 0; k < N / 2; k++) {
int ci = -1;
if (!dire) {
ci=-ci;
}
Complex wnk = getWnk(N, k, ci);
Complex wnkX1 = wnk.multiply(X1[k]);
y[k] = X0[k].plus(wnkX1);
y[k+N/2] = X0[k].minus(wnkX1);
}
return y;
}
private static Complex getWnk(int N, int k, int n) {
double T = 2 * Math.PI / N;
double kth = T * k * n;
Complex wk = new Complex(Math.cos(kth), Math.sin(kth));
return wk;
}
}