yanchang
yanchang
发布于 2026-05-07 / 0 阅读
0
0

十分简明易懂的FFT(快速傅里叶变换)

快速傅里叶变换 (Fast Fourier Transform, 简称 FFT) 是离散傅里叶变换 (DFT) 的一种快速、高效的算法。它由 J.W. Cooley 和 T.W. Tukey 在 1965 年提出。

在处理多项式乘法(或卷积)时,朴素的高精度乘法需要O(n2)O(n^2) 的时间复杂度。而 FFT 巧妙地利用了离散傅氏变换的奇偶、虚实等特性,能将时间复杂度大幅优化至O(nlog2n)O(n \log_2 n)。被变换的抽样点数NN 越多,FFT 算法计算量的节省就越显著。


一、 多项式的两种表示法

FFT 的核心思想是:用O(nlog2n)O(n \log_2 n) 的时间将一个用系数表示的多项式转换成它的点值表示,完成乘法后再转换回来。

1.1 系数表示法

一个n1n-1nn 项多项式f(x)f(x) 可以表示为:

f(x)=i=0n1aixif(x) = \sum_{i=0}^{n-1} a_i x^i

也可以直接用每一项的系数集合来表示:

f(x)={a0,a1,a2,,an1}f(x) = \{a_0, a_1, a_2, \cdots, a_{n-1}\}

1.2 点值表示法

如果把多项式放到平面直角坐标系里面看成一个函数,代入nn 个不同的xx,会得出nn 个不同的yy

nn 个点可以唯一确定该多项式(即有且仅有一个n1n-1 次多项式满足k,f(xk)=yk\forall k, f(x_k) = y_k,相当于解nn 元一次方程组)。因此,f(x)f(x) 还可以表示为:

f(x)={(x0,f(x0)),(x1,f(x1)),,(xn1,f(xn1))}f(x) = \{(x_0, f(x_0)), (x_1, f(x_1)), \cdots, (x_{n-1}, f(x_{n-1}))\}

这就是点值表示法。

1.3 乘法复杂度的区别

  • 系数表示法: 若将多项式A(x)A(x)B(x)B(x) 相乘,需要枚举AA 每一位的系数与BB 每一位的系数相乘,时间复杂度为O(n2)O(n^2)

  • 点值表示法: 若两者的点值表示在相同的xix_i 处取值,它们相乘后的多项式h(x)h(x) 的点值只需将对应的纵坐标直接相乘:

    h(x)={(x0,f(x0)g(x0)),,(xn1,f(xn1)g(xn1))}h(x) = \{(x_0, f(x_0) \cdot g(x_0)), \cdots, (x_{n-1}, f(x_{n-1}) \cdot g(x_{n-1}))\}

    这个过程只需要枚举一次,时间复杂度仅为O(n)O(n)

概念明确: 朴素的系数转点值的算法叫 DFT(离散傅里叶变换),点值转系数叫 IDFT(离散傅里叶逆变换)


二、 前置知识:复数与单位根

2.1 复数基础

我们把形如z=a+biz = a + bia,bRa,b \in \mathbb{R})的数称为复数,其中aa 为实部, bb为虚部,ii 为虚数单位。

定义i2=1i^2 = -1,引入复数后就可以表示负数的平方根,如7=7i\sqrt{-7} = \sqrt{7}i

  • 复平面: 复数可以看作复平面直角坐标系上的一个点(a,b)(a,b) 或代表它的向量。

  • 模长: 复数zz 到原点的距离,记为z=a2+b2|z| = \sqrt{a^2 + b^2}

  • 共轭复数:z=a+biz = a + bi 的共轭复数为z=abi\overline{z} = a - bi(即虚部取反)。

2.2 复数的运算性质

  • 加法:(a+bi)+(c+di)=(a+c)+(b+d)i(a + bi) + (c + di) = (a + c) + (b + d)i(满足向量的平行四边形法则)。

  • 乘法:(a+bi)(c+di)=(acbd)+(ad+bc)i(a + bi) \cdot (c + di) = (ac - bd) + (ad + bc)i

  • 乘法的几何意义(极其重要): 模长相乘,极角相加

    (a1,θ1)(a2,θ2)=(a1a2,θ1+θ2)(a_1, \theta_1) \cdot (a_2, \theta_2) = (a_1 a_2, \theta_1 + \theta_2)

    复数相加也满足平行四边形法则A B + A D = A C

    复数相乘还有一个值得注意的小性质: 模长相乘,极角相加


三、 DFT 与 FFT 核心解析

(注:从这里开始,所有的项数nn 都默认为22 的整数次幂)

3.1 离散傅里叶变换 (DFT) 与 单位根ω\omega

任意取nnxx 值代入计算多项式,暴力计算xk0,xk1,,xkn1x_k^0, x_k^1, \cdots, x_k^{n-1} 依然需要O(n2)O(n^2) 的时间。

傅里叶提出,代入单位圆上的等分点可以极大简化运算。以半径为11 的单位圆为例,将其nn 等分,从(1,0)(1,0) 开始逆时针标号。第kk 个点代表的复数称为nn 次单位根,记为ωnk\omega_n^k

ωnk=cos(2kπn)+isin(2kπn)\omega_n^k = \cos\left(\frac{2k\pi}{n}\right) + i\sin\left(\frac{2k\pi}{n}\right)

结合欧拉公式eix=cosx+isinxe^{ix} = \cos x + i \sin x(特例:eiπ+1=0e^{i\pi} + 1 = 0 ),单位根具有以下优秀性质,这也是推导 FFT 分治的基础:

  1. 折半引理:ωnk=ω2n2k\omega_n^k = \omega_{2n}^{2k} (两者表示的复数点相同)。

  2. 对称引理:ωnk+n/2=ωnk\omega_n^{k + n/2} = -\omega_n^k (在单位圆上关于原点对称)。

  3. 周期性:ωn0=ωnn=1\omega_n^0 = \omega_n^n = 1

3.2 快速傅里叶变换 (FFT) 的分治思想

DFT 仍然是暴力的O(n2)O(n^2),但通过单位根的性质,我们可以利用分治对其进行优化。

设多项式A(x)=a0+a1x+a2x2++an1xn1A(x) = a_0 + a_1x + a_2x^2 + \cdots + a_{n-1}x^{n-1}

A(x)A(x) 下标的奇偶性将其分成两半,并在奇数部分提一个xx 出来:

A(x)=(a0+a2x2+)+x(a1+a3x2+)A(x) = (a_0 + a_2x^2 + \cdots) + x(a_1 + a_3x^2 + \cdots)

设两个新多项式:

A1(x)=a0+a2x+A_1(x) = a_0 + a_2x + \cdots

A2(x)=a1+a3x+A_2(x) = a_1 + a_3x + \cdots

则有原多项式重组公式:A(x)=A1(x2)+xA2(x2)A(x) = A_1(x^2) + xA_2(x^2)

ωnk\omega_n^k (k<n/2k < n/2 ) 代入上式:

A(ωnk)=A1(ωn2k)+ωnkA2(ωn2k)=A1(ωn/2k)+ωnkA2(ωn/2k)A(\omega_n^k) = A_1(\omega_n^{2k}) + \omega_n^k A_2(\omega_n^{2k}) = A_1(\omega_{n/2}^k) + \omega_n^k A_2(\omega_{n/2}^k)

利用对称引理,将另一半ωnk+n/2\omega_n^{k + n/2} 代入:

A(ωnk+n/2)=A1(ωn/2k)ωnkA2(ωn/2k)A(\omega_n^{k + n/2}) = A_1(\omega_{n/2}^k) - \omega_n^k A_2(\omega_{n/2}^k)

核心结论:

计算A(ωnk)A(\omega_n^k)A(ωnk+n/2)A(\omega_n^{k + n/2}) 时,公式的后半段只有符号不同

这意味着,在分治回溯时,我们只要知道前一半序列A1(ωn/2k)A_1(\omega_{n/2}^k)A2(ωn/2k)A_2(\omega_{n/2}^k) 的值,就可以直接算出后一半序列的答案。

每次递归一分为二,当n=1n=1 时只有一个常数项直接 return。这成功将时间复杂度降到了O(nlog2n)O(n \log_2 n)

3.3 快速傅里叶逆变换 (IFFT)

计算完卷积后,我们需要将点值表示的多项式转回系数表示。

如果用普通的 IDFT 暴力解依然是O(n2)O(n^2)。如何使用 FFT 的框架在O(nlog2n)O(n \log_2 n) 内解决?

数学推导表明: 将多项式在分治的过程中,乘上的单位根全部替换为其共轭复数ωnk\omega_n^{-k} 进行同样的 FFT 操作。分治完成后,将得到的每一项结果除以nn,即为原多项式的每一项系数。


评论