[EE261学习笔记] 15.快速傅里叶变换(FFT)原理

本文介绍了快速傅里叶变换(FFT)的基本概念及其相对于离散傅里叶变换(DFT)的优势。通过数学推导展示了如何利用递归方式降低计算复杂度,最终达到O(NlogN)的时间效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单回顾

快速傅里叶变换,其实是离散傅里叶变换的一种改进算法

我们先来回忆一下离散傅里叶变换(DFT):

Ff[m]‾=∑n=0N−1f[n]‾ω[m]‾−n(1)\underline{\mathscr{F}f[m]} = \sum_{n=0}^{N-1} \underline{f[n]} \underline{\omega[m]}^{-n} \tag1Ff[m]=n=0N1f[n]ω[m]n(1)

其中 ω[m]‾=e2πimN\underline{\omega[m]} = e^{2\pi i\frac{m}{N}}ω[m]=e2πiNm

对应的矩阵形式为:

[Ff[0]‾Ff[1]‾⋮Ff[N−1]‾]=[11⋯11ω‾−1⋅1⋯ω‾−1⋅(N−1)⋮⋮⋱⋮1ω‾−(N−1)⋅1⋯ω‾−(N−1)2][f[0]‾f[1]‾⋮f[N−1]‾]\begin{bmatrix} \underline{\mathscr{F}f[0]}\\ \underline{\mathscr{F}f[1]}\\ \vdots\\ \underline{\mathscr{F}f[N-1]} \end{bmatrix} = \begin{bmatrix} 1 & 1 & \cdots & 1 \\ 1 & \underline{\omega}^{-1 \cdot 1} & \cdots & \underline{\omega}^{- 1 \cdot (N-1)} \\ \vdots & \vdots & \ddots & \vdots \\ 1 & \underline{\omega}^{-(N-1) \cdot 1} & \cdots & \underline{\omega}^{-(N-1)^2} \end{bmatrix} \begin{bmatrix} \underline{f[0] } \\ \underline{f[1]} \\ \vdots\\ \underline{f[N-1]} \end{bmatrix}Ff[0]Ff[1]Ff[N1]=1111ω11ω(N1)11ω1(N1)ω(N1)2f[0]f[1]f[N1]

不难发现,如果要对 NNN 个采样点进行DFT,则时间复杂度为 o(N2)o \left( N^2\right)o(N2)

接下来,我们将讲解时间复杂度为 o(Nlog⁡N)o \left( N \log N \right)o(NlogN) 的FFT算法

为了书写方便,我们记

ω‾[p,q]=e2πiqp(2)\underline{\omega}[p, q] = e^{2\pi i \frac{q}{p}} \tag 2ω[p,q]=e2πipq(2)

这样,ω[m]‾\underline{\omega[m]}ω[m]就可以改写为

ω[m]‾=e2πimN=ω‾[N,m]\underline{\omega[m]} = e^{2\pi i \frac{m}{N}} = \underline{\omega}[N, m]ω[m]=e2πiNm=ω[N,m]

同时,不难发现,

ω‾[N,n+m]=e2πin+mN=e2πinNe2πimN=ω‾[N,n]ω‾[N,m]\underline{\omega}[N, n+m] = e^{2\pi i \frac{n+m}{N}} = e^{2\pi i \frac{n}{N}}e^{2\pi i \frac{m}{N}} = \underline{\omega}[N, n]\underline{\omega}[N, m]ω[N,n+m]=e2πiNn+m=e2πiNne2πiNm=ω[N,n]ω[N,m]

ω‾[N2,−nm]=e−2πinmN2=e−2πi2nmN=ω‾[N,−2nm]\underline{\omega}[\frac{N}{2}, -nm] = e^{-2\pi i \frac{nm}{\frac{N}{2}}} = e^{-2\pi i \frac{2nm}{N}} = \underline{\omega}[N, -2nm]ω[2N,nm]=e2πi2Nnm=e2πiN2nm=ω[N,2nm]


FFT推导

FFT的核心思想就是:将DFT的N×NN \times NN×N矩阵该写为对几个N2×N2\frac{N}{2} \times \frac{N}{2}2N×2N的矩阵的操作,并用这种方式进行递归,最后得到FFT

首先,我们将(1)(1)(1)式拆分为奇数、偶数两部分,即

Ff[m]‾=∑n=0N−1f[n]‾ω[m]‾−n=(f[0]‾ω[m]‾−0+f[2]‾ω[m]‾−2+⋯+f[N−2]‾ω[m]‾−(N−2))+(f[1]‾ω[m]‾−1+f[3]‾ω[m]‾−3+⋯+f[N−1]‾ω[m]‾−(N−1))=∑n=0N2−1f[2n]‾ω[m]‾−2n+∑n=0N2−1f[2n+1]‾ω[m]‾−(2n+1)\begin{aligned} \underline{\mathscr{F}f[m]} &= \sum_{n=0}^{N-1} \underline{f[n]} \underline{\omega[m]}^{-n}\\ & = \left( \underline{f[0]} \underline{\omega[m]}^{-0} + \underline{f[2]} \underline{\omega[m]}^{-2} + \dots + \underline{f[N-2]} \underline{\omega[m]}^{-\left(N-2 \right)} \right) + \left( \underline{f[1]} \underline{\omega[m]}^{-1} + \underline{f[3]} \underline{\omega[m]}^{-3} + \dots + \underline{f[N-1]} \underline{\omega[m]}^{-\left(N-1 \right)} \right)\\ &=\sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n]} \underline{\omega[m]}^{-2n} + \sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n+1]} \underline{\omega[m]}^{-(2n+1)} \end{aligned}Ff[m]=n=0N1f[n]ω[m]n=(f[0]ω[m]0+f[2]ω[m]2++f[N2]ω[m](N2))+(f[1]ω[m]1+f[3]ω[m]3++f[N1]ω[m](N1))=n=02N1f[2n]ω[m]2n+n=02N1f[2n+1]ω[m](2n+1)

利用 (2)(2)(2) 式,可将上式改写为

Ff[m]‾=∑n=0N2−1f[2n]‾ω‾[N,−2nm]+∑n=0N2−1f[2n+1]‾ω‾[N,−(2n+1)m]=∑n=0N2−1f[2n]‾ω‾[N,−2nm]+∑n=0N2−1f[2n+1]‾ω‾[N,−2nm]ω‾[N,−m]=∑n=0N2−1f[2n]‾ω‾[N2,−nm]+ω‾[N,−m]∑n=0N2−1f[2n+1]‾ω‾[N2,−nm](3)\begin{aligned} \underline{\mathscr{F}f[m]} &=\sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n]} \underline{\omega}[N, -2nm] + \sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n+1]} \underline{\omega}[N, -(2n+1)m]\\ &=\sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n]} \underline{\omega}[N, -2nm] + \sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n+1]} \underline{\omega}[N, -2nm]\underline{\omega}[N, -m]\\ &=\sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n]} \underline{\omega}[\frac{N}{2}, -nm] + \underline{\omega}[N, -m] \sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n+1]} \underline{\omega}[\frac{N}{2}, -nm]\tag 3 \end{aligned}Ff[m]=n=02N1f[2n]ω[N,2nm]+n=02N1f[2n+1]ω[N,(2n+1)m]=n=02N1f[2n]ω[N,2nm]+n=02N1f[2n+1]ω[N,2nm]ω[N,m]=n=02N1f[2n]ω[2N,nm]+ω[N,m]n=02N1f[2n+1]ω[2N,nm](3)

注意我们要使用递归来计算的话,必须把式子写成矩阵形式,那么(3)(3)(3)式就可以写为:

F‾Nf[m]‾=FN2feven[m]‾+ω‾[N,−m]FN2fodd[m]‾(4)\underline\mathscr{F}_N \underline{f[m]} = \underline{\mathscr{F}_{\frac{N}{2}}f_\text{even}[m]} + \underline{\omega}[N, -m]\underline{\mathscr{F}_{\frac{N}{2}}f_\text{odd}[m]} \tag4FNf[m]=F2Nfeven[m]+ω[N,m]F2Nfodd[m](4)

我们仔细看看从 (3)(3)(3) 式的求和形式到 (4)(4)(4) 的矩阵矩阵形式,(3)(3)(3) 式完全是没有问题的,但是 (4)(4)(4) 式却有问题: (4)(4)(4) 式中的 F‾N2\underline\mathscr{F}_{\frac{N}{2}}F2NN2×N2\frac{N}{2} \times \frac{N}{2}2N×2N 的矩阵,那么与之相乘的矩阵必然有 N2\frac{N}{2}2N 行,也就是说 m≤N2−1m \leq \frac{N}{2}-1m2N1。换句话说,(4)(4)(4) 式计算出的其实是 F‾N\underline\mathscr{F}_NFN 的前半部分。

那么对于 m∈[N2,N−1]m \in [\frac{N}{2}, N-1]m[2N,N1] 的情况,应该如何写出相应的矩阵形式呢?我们将 (3)(3)(3) 式左边的系数写成 m+N2m+\frac{N}{2}m+2N,这样一来,mmm 的取值依然是 [0,N2−1][0, \frac{N}{2}-1][0,2N1]。于是就有:

Ff[m+N2]‾=∑n=0N2−1f[2n]‾ω‾[N2,−n(m+N2)]+ω‾[N,−(m+N2)]∑n=0N2−1f[2n+1]‾ω‾[N2,−n(m+N2)]=∑n=0N2−1f[2n]‾ω‾[N2,−nm]ω‾[N2,−nN2]+ω‾[N,−m]ω‾[N,−N2]∑n=0N2−1f[2n+1]‾ω‾[N2,−nm]ω‾[N2,−nN2](5)\begin{aligned} \underline{\mathscr{F}f[m+\frac{N}{2}]} & = \sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n]} \underline{\omega}[\frac{N}{2}, -n \left(m+\frac{N}{2}\right) ] \\ & +\underline{\omega}[N, -\left(m+\frac{N}{2}\right)] \sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n+1]} \underline{\omega}[\frac{N}{2}, -n\left(m+\frac{N}{2}\right)] \\ & = \sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n]} \underline{\omega}[\frac{N}{2}, -nm ] \underline{\omega}[\frac{N}{2}, -n \frac{N}{2}]\\ &+\underline{\omega}[N, -m] \underline{\omega}[N, -\frac{N}{2}] \sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n+1]} \underline{\omega}[\frac{N}{2}, -nm] \underline{\omega}[\frac{N}{2}, -n\frac{N}{2}] \tag5 \end{aligned}Ff[m+2N]=n=02N1f[2n]ω[2N,n(m+2N)]+ω[N,(m+2N)]n=02N1f[2n+1]ω[2N,n(m+2N)]=n=02N1f[2n]ω[2N,nm]ω[2N,n2N]+ω[N,m]ω[N,2N]n=02N1f[2n+1]ω[2N,nm]ω[2N,n2N](5)

注意到,

ω‾[N2,−nN2]=e−2πin=1\underline{\omega}[\frac{N}{2}, -n\frac{N}{2}] = e^{-2\pi in} = 1ω[2N,n2N]=e2πin=1

ω‾[N,−N2]=e−πi=−1\underline{\omega}[N, -\frac{N}{2}] = e^{-\pi i} = -1ω[N,2N]=eπi=1

带入 (5)(5)(5) 式,有:

Ff[m+N2]‾=∑n=0N2−1f[2n]‾ω‾[N2,−nm]−ω‾[N,−m]∑n=0N2−1f[2n+1]‾ω‾[N2,−nm]\underline{\mathscr{F}f[m+\frac{N}{2}]} = \sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n]} \underline{\omega}[\frac{N}{2}, -nm ] - \underline{\omega}[N, -m] \sum_{n=0}^{\frac{N}{2}-1} \underline{f[2n+1]} \underline{\omega}[\frac{N}{2}, -nm]Ff[m+2N]=n=02N1f[2n]ω[2N,nm]ω[N,m]n=02N1f[2n+1]ω[2N,nm]

写成矩阵的形式,即

F‾Nf[m+N2]‾=FN2feven[m]‾−ω‾[N,−m]FN2fodd[m]‾(6)\underline\mathscr{F}_N \underline{f[m+\frac{N}{2}]} = \underline{\mathscr{F}_{\frac{N}{2}}f_{even}[m]} - \underline{\omega}[N, -m]\underline{\mathscr{F}_{\frac{N}{2}}f_{odd}[m]} \tag6FNf[m+2N]=F2Nfeven[m]ω[N,m]F2Nfodd[m](6)

结合 (4)(4)(4)(6)(6)(6) 两式,我们可以得到FFT的矩阵递归式:

F‾Nf[m]‾=FN2feven[m]‾+ω‾[N,−m]FN2fodd[m]‾\huge\underline\mathscr{F}_N \underline{f[m]} = \underline{\mathscr{F}_{\frac{N}{2}}f_\text{even}[m]} + \underline{\omega}[N, -m]\underline{\mathscr{F}_{\frac{N}{2}}f_\text{odd}[m]}FNf[m]=F2Nfeven[m]+ω[N,m]F2Nfodd[m]

F‾Nf[m+N2]‾=FN2feven[m]‾−ω‾[N,−m]FN2fodd[m]‾\huge\underline\mathscr{F}_N \underline{f[m+\frac{N}{2}]} = \underline{\mathscr{F}_{\frac{N}{2}}f_{even}[m]} - \underline{\omega}[N, -m]\underline{\mathscr{F}_{\frac{N}{2}}f_\text{odd}[m]}FNf[m+2N]=F2Nfeven[m]ω[N,m]F2Nfodd[m]

其中 m∈[0,N2−1]m\in [0, \frac{N}{2}-1]m[0,2N1],第一个等式为前 N2\frac{N}{2}2N 项,第二个等式为后 N2\frac{N}{2}2N

这个式子很明确地告诉我们:

FFT实际上就是将DFT的矩阵,通过一定的方式进行拆分,从而降低时间复杂度的一种算法


FFT的时间复杂度

有了递归式,我们就可以来算时间复杂度。

方便起见,我们将矩阵写成 [n×m]\left[ n \times m \right][n×m],其中 nnnmmm 分别表示行列数。并设 N=2kN = 2^kN=2k

  1. 那么前 N2\frac{N}{2}2N 项就可以写成

[N2×N2]+CN[N2×N2]\left[ \frac{N}{2} \times \frac{N}{2} \right] + C_N \left[ \frac{N}{2} \times \frac{N}{2} \right][2N×2N]+CN[2N×2N]

其中 CNC_NCN 为一常数,该式花费的时间为 o([N2×N2])+1+o([N2×N2])o\left( \left[ \frac{N}{2} \times \frac{N}{2} \right] \right) + 1 + o\left( \left[ \frac{N}{2} \times \frac{N}{2} \right] \right)o([2N×2N])+1+o([2N×2N]),其中 111 就是常数相乘的操作

对于后 N2\frac{N}{2}2N 项,由于对应的矩阵、常数都是相同的,因此只需要额外进行 111 次操作即可

  1. 我们把 n×nn \times nn×n 的矩阵记为 [n][n][n],并把 mmm 个不同的常数相乘记为 CmC^mCm,则如下图

这里写图片描述

注意图中 1+2⋯+2k−11+2 \dots + 2^{k-1}1+2+2k1 是前文提到的后 N2\frac{N}{2}2N 项的计算量,需要进行累加计算。到最后一项时,它的累积值为 2n−12^n-12n1

不难发现,递归至最后一项时,总计算次数应为(图中最后一行以及虚线框内):

0⋅(0k)+1⋅(1k)+⋯+k⋅(kk)+(2k)+(2k−1)+(2k)(7)0\cdot\binom{0}{k} + 1\cdot\binom{1}{k} + \dots + k\cdot \binom{k}{k} + (2^k) + (2^k-1) +(2^k)\tag70(k0)+1(k1)++k(kk)+(2k)+(2k1)+(2k)(7)

简单解释一下上式

  • 前面的各项排列组合表示的是各个常数 CxC^xCx 所需的计算时间,如系数 CkC^kCk 只在最后一个一阶矩阵前出现,计算量为 k⋅(kk)=kk\cdot \binom{k}{k}=kk(kk)=k 次,又如系数 C1C^1C1 必然会出现 (1k)\binom{1}{k}(k1) 次,因此计算量为 1⋅(1k)=k1\cdot \binom{1}{k}=k1(k1)=k
  • 第一个 2n2^n2n 表示的是所有 111 阶矩阵的计算时间总和;
  • 2n−12^n-12n1 表示的是后 N2\frac{N}{2}2N 项的计算量;
  • 第二个 2n2^n2n 表示的是计算所有加号花费的时间

(7)(7)(7) 式不容易计算,但是我们可以直观地估计一下,对于前面的阶乘项,最多用时为 kkk 次,最少为 111 次,那么不严格地估计一下,我们取平均 k+12\frac{k+1}{2}2k+1 次,这样共需要计算 NNN 次(有 NNN[1][1][1]),因此时间复杂度应为:

o((Nk2)+3N−1)=o(12Nlog⁡2N+3N−1)=o(Nlog⁡2N)o\left( \left( N\frac{k}{2} \right) +3N-1 \right) = o\left( \frac{1}{2} N \log _2 N +3N-1 \right) = o\left( N \log _2 N \right) o((N2k)+3N1)=o(21Nlog2N+3N1)=o(Nlog2N)

因此,FFT的时间复杂度就是

o(Nlg⁡N) o\left( N \lg N \right) o(NlgN)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值