多项式与快速傅里叶变换

134 阅读13分钟

多项式

什么是多项式?

形如:

P(x)=anxn+an1xn1++a0,n{0,1,2,3}P(x) = a_nx^n+a_{n-1}x^{n-1}+\cdots+a_0,\quad n\in\{0,1,2,3\cdots\}

对于确定的 P(x)P(x) 我们需要知道 n+1n+1 个系数,或者需要 n+1n+1 个点 (xi,P(xi))\left(x_i,P(x_i)\right)

如果存在两个多项式 P(x)P(x)Q(x)Q(x) 都过 n+1n+1 个点,则

(P(x0)P(x1)P(x2)P(xn))=(1x0x02x0n11x1x12x1n11x2x22x2n11xnxn2xnn1)(p0p1p2pn)\begin{pmatrix} P(x_0) \\ P(x_1) \\ P(x_2) \\ \vdots \\ P(x_n) \end{pmatrix} = \begin{pmatrix} 1 & x_0 & x_0^2 & \cdots & x_0^{n-1} \\ 1 & x_1 & x_1^2 & \cdots & x_1^{n-1} \\ 1 & x_2 & x_2^2 & \cdots & x_2^{n-1} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & x_n & x_n^2 & \cdots & x_n^{n-1} \end{pmatrix} \begin{pmatrix} p_0 \\ p_1 \\ p_2 \\ \vdots \\ p_{n} \end{pmatrix}
(Q(x0)Q(x1)Q(x2)Q(xn))=(1x0x02x0n11x1x12x1n11x2x22x2n11xnxn2xnn1)(q0q1q2qn)\begin{pmatrix} Q(x_0) \\ Q(x_1) \\ Q(x_2) \\ \vdots \\ Q(x_n) \end{pmatrix} = \begin{pmatrix} 1 & x_0 & x_0^2 & \cdots & x_0^{n-1} \\ 1 & x_1 & x_1^2 & \cdots & x_1^{n-1} \\ 1 & x_2 & x_2^2 & \cdots & x_2^{n-1} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & x_n & x_n^2 & \cdots & x_n^{n-1} \end{pmatrix} \begin{pmatrix} q_0 \\ q_1 \\ q_2 \\ \vdots \\ q_{n} \end{pmatrix}

因为 Q(xi)=P(xi)Q(x_i)=P(x_i) 并且范德蒙行列式满秩, 所以 pi=qip_i = q_i

什么是多项式乘法?

我所要讲的是现在已知两个多项式 A(x)A(x)B(x)B(x) ,我们应该如何得到两个多项式的乘积C(x)C(x)

A(x)=apxp+ap1xp1++a0B(x)=bqxq+bq1xq1++b0C(x)=A(x)B(x)=crxr+cr1xr1++c0}\begin{align} A(x) &= a_px^p+a_{p-1}x^{p-1}+\cdots+a_0\\ B(x) &= b_qx^q+b_{q-1}x^{q-1}+\cdots+b_0 \\ C(x) &= A(x) \, B(x)= c_{r}x^{r}+c_{r-1}x^{r-1}+\cdots+c_0\} \end{align}

上述的公式中 a(x),b(x)a(x),b(x) 已知,crc_r 未知 通常的算法:多项式乘法(假设 pqp \geqslant q

apxp++aqxq+aq1xq1++a1x+a0bqxq+bq1xq1++b1x+b0apb0xp++aqb0xq+aq1b0xq1++a1b0x+a0b0apb1xp+1++aq1b1xq+aq2b1xq1++a0b1xapbqxp+q++a0bqxqcp+qxp+q++cqxq+cq1xq1++c1x1+c0\begin{align} a_px^p + \cdots+ a_{q}&x^{q}+a_{q - 1}x^{q-1}+\cdots+a_1x + a_0\\ b_q&x^q + b_{q - 1}x^{q-1}+\cdots+b_1x + b_0\\ \hline a_pb_0x^p+\cdots+a_{q}b_0&x^{q}+a_{q - 1}b_0x^{q-1}+\cdots+a_1b_0x+a_0b_0\\ a_pb_1x^{p + 1}+\cdots+a_{q - 1}b_1&x^{q}+a_{q - 2}b_1x^{q-1}+\cdots+a_0b_1x\\ \vdots \\ a_pb_qx^{p + q}+\cdots+a_{0}b_q&x^{q}\\ \hline c_{p+q}x^{p+q}+\cdots+c_{q}&x^{q}+c_{q-1}x^{q-1}+\cdots+c_{1}x^{1}+c_0 \end{align}

多项式乘法代码实现

# 定义多项式系数
a = [1, 2, 3, 4, 5]  # 表示多项式 x^4 + 2x^3 + 3x^2 + 4x + 5
b = [2, 3, 4, 5]     # 表示多项式 2x^3 + 3x^2 + 4x + 5

# 初始化结果多项式的系数数组
# 结果多项式的最大次数为 len(a) + len(b) - 2
result_length = len(a) + len(b) - 1
result = [0] * result_length

# 反转系数数组以便从低次项到高次项进行计算
a_reversed = a[::-1]
b_reversed = b[::-1]

# 多项式乘法计算
for j in range(len(b_reversed)):
    for i in range(len(a_reversed)):
        result[i + j] += a_reversed[i] * b_reversed[j]

# 反转结果数组以恢复正确的次序
result = result[::-1]

# 打印结果
print(result)


时间复杂度

我们讨论一下计算的复杂度 所需要的计算:

  • 浮点数加法 pqp \cdot q
  • 浮点数乘法 pqp \cdot q

现在我想告诉你的是有一种算法可以将算法的复杂度减到 O(Nlog2N)O(N \cdot \log_2N)

我们即将用到的大杀器 快速傅里叶变换

傅里叶变换

泰勒级数

f(x)=anxn+an1xn1++a0,n{0,1,2,3}f(x)=a_nx^n+a_{n-1}x^{n-1}+\cdots+a_0,\quad n\in\{0,1,2,3\cdots\}

其中{xnn{0,1,2,3}\{x^n| n\in\{0,1,2,3\cdots\}是一组基(虽然不是正交基)aia_i是这一组基坐标系下的坐标 。

可以使用一些判别法求出泰勒级数的收敛半径

傅里叶级数

在讨论傅里叶级数之前我们先证明一些之后可能用到的小推论

核函数 DN(x)D_N(x)

DN(x)=12+n=1Ncosnx=12+cosx+cos2x+cos3x++cosNx=2sinx22+2sinx2cosx+2sinx2cos2x+2sinx2cos3x++2sinx2cosNx2sinx2=sinx2+sin(x2+x)+sin(x2x)+sin(x2+2x)+sin(x22x)++sin(x2+Nx)+sin(x2Nx)2sinx2=sinx2+sin(3x2)sinx2+sin(5x2)sin(3x2)++sin((2N+1)x2)sin((2N1)x2)2sinx2=sin(2N+1)x22sinx2\begin{align} D_N(x) &= \frac{1}{2}+ \sum_{n = 1}^{N} \cos nx \\ &= \frac{1}{2} + \cos x + \cos 2x + \cos 3x + \cdots + \cos Nx \\ &= \frac{ \frac{ 2 \sin \frac {x} {2}}{2} + 2 \sin \frac {x} {2} \cos x + 2 \sin \frac {x} {2} \cos 2x + 2 \sin \frac {x} {2} \cos 3x + \cdots + 2 \sin \frac {x} {2} \cos Nx }{ 2 \sin \frac {x} {2} } \\ &= \frac{ \sin \frac {x} {2} + \sin \left(\frac {x} {2}+x\right) + \sin \left(\frac {x} {2}-x\right) + \sin \left(\frac {x} {2}+2x\right) + \sin \left(\frac {x} {2}-2x\right) + \cdots + \sin \left(\frac {x} {2}+Nx\right) + \sin \left(\frac {x} {2}-Nx\right) }{ 2 \sin \frac {x} {2} } \\ &= \frac{ \sin \frac {x} {2} + \sin \left(\frac {3x} {2}\right) - \sin \frac {x} {2} + \sin \left(\frac {5x} {2}\right) - \sin \left(\frac {3x} {2}\right) + \cdots + \sin \left(\frac {(2N+1)x} {2}\right) - \sin \left(\frac {(2N-1)x} {2}\right) }{ 2 \sin \frac {x} {2} } \\ &= \frac {\sin \frac {(2N+1)x} {2}} { 2 \sin \frac {x} {2}} \end{align}

核函数 DN(x)D_N(x) 的积分

0πDN(x)dx=π21π0π2DN(x)dx=11π0π2sDN(x)dx=s\begin{align} \int_0^{\pi} D_N(x) \,\text{d} x &= \frac{\pi}{2} \\ \frac{1}{\pi}\int_0^{\pi} 2 D_N(x) \,\text{d} x &= 1 \\ \frac{1}{\pi}\int_0^{\pi} 2 s D_N(x) \,\text{d} x &= s \\ \end{align}

三角函数的正交

cos(mx)\cos(mx)cos(nx)\cos(nx)mnm \ne n 时正交
sin(mx)\sin(mx)sin(nx)\sin(nx)mnm \ne n 时正交
cos(mx)\cos(mx)sin(nx)\sin(nx)mnm \ne n 时正交

验证三角函数族{1,sin(nx),cos(nx)n{1,2,3}\{ \left. 1,sin(nx),cos(nx) \right | n\in\{1,2,3\cdots\}在区间[π,π][-\pi,\pi]上的正交性

我们使用以下内积定义:

f,g=ππf(x)g(x)dx\langle f, g \rangle = \int_{-\pi}^{\pi} f(x) g(x) \,\text dx

证明:

ππcos(mx)cos(nx)dx=0mn使用三角恒等式ππcos(mx)cos(nx)dx=12ππcos((m+n)x)dx+12ππcos((mn)x)dx因为cos(kx)在一个周期内的积分为零ππcos(mx)cos(nx)dx=0m=n在一个周期内的积分为 πππcos(mx)cos(nx)dx=π\begin{align} \int_{-\pi}^{\pi} \cos(mx) \cos(nx) \, \text{d}x &= 0 \quad \text{当} \quad m \neq n \\ \Downarrow \quad &\text{使用三角恒等式} \\ \int_{-\pi}^{\pi} \cos(mx) \cos(nx) \, \text{d}x &= \frac{1}{2} \int_{-\pi}^{\pi} \cos((m+n)x) \, \text{d}x + \frac{1}{2} \int_{-\pi}^{\pi} \cos((m-n)x) \, \text{d}x \\ \Downarrow \quad &\text{因为} \cos(kx) \text{在一个周期内的积分为零} \\ \int_{-\pi}^{\pi} \cos(mx) \cos(nx) \, \text{d}x &= 0 \\ \Downarrow \quad &\text{若} m = n \text{在一个周期内的积分为 } \pi \\ \int_{-\pi}^{\pi} \cos(mx) \cos(nx) \, \text{d}x &= \pi \end{align}

计算傅里叶级数的系数

若函数f(x)f(x)可以展开成为a0,an,bna_0, a_{n}, b_{n}成立

f(x)=a02+n=1(ancosnx+bnsinnx)f(x)=\frac{a_{0}}{2}+\sum_{n = 1}^{\infty}(a_{n}\cos nx + b_{n}\sin nx)

计算a0,an,bna_0,a_n,b_n分别是多少

f(x)=a02+n=1(ancosnx+bnsinnx) 同时乘 cosnx 然后 ππdxππf(x)cosnxdx=anπan=1πππf(x)cosnxdxbn=1πππf(x)sinnxdxan=anbn=bn\begin{align} f(x)&=\frac{a_{0}}{2}+\sum_{n = 1}^{\infty}(a_{n}\cos nx + b_{n}\sin nx)\\ &\Downarrow \text{ 同时乘 } \cos nx \text{ 然后 } \int_{-\pi}^\pi \text{d}x \\ \int_{-\pi}^\pi f(x) \cos nx \text{d}x&=a_n \pi \\ &\Downarrow \\ a_n &=\frac{1}{\pi} \int_{-\pi}^\pi f(x)\cos nx \, \text{d}x \\ b_n &=\frac{1}{\pi} \int_{-\pi}^\pi f(x)\sin nx \, \text{d}x \\ &\Downarrow \\ a_{-n} &= a_{n} \\ b_{-n} &= -b_{n} \\ \end{align}

贝塞尔不等式的证明

贝塞尔不等式: 其中f(x)f(x)为任意函数

a022+n=1(an2+bn2)1πππf(x)2dx\frac{a_0^2}{2} + \sum_{n=1}^{\infty} (a_n^2 + b_n^2) \leq \frac{1}{\pi} \int_{-\pi}^{\pi} f(x)^2 \, dx

要证明贝塞尔不等式,我们可以考虑误差项。 定义 SN(x)S_N(x) 为傅里叶级数的第 NN 部分和:

SN(x)=a02+n=1N(ancos(nx)+bnsin(nx))S_N(x) = \frac{a_0}{2} + \sum_{n=1}^{N} \left( a_n \cos(nx) + b_n \sin(nx) \right)

误差项 RN(x)R_N(x) 为:

RN(x)=f(x)SN(x)R_N(x) = f(x) - S_N(x)

误差项 RN2(x)R_N^2(x) 为:

ππRN2(x)dx=ππ(f(x)SN(x))2dx=ππf2(x)2f(x)SN(x)+SN2(x)dx=ππf2(x)dx2(2πa024+πn=1Nan2+bn2)+(2πa024+πn=1Nan2+bn2)=ππf2(x)dx(2πa024+πn=1Nan2+bn2)=ππf2(x)dxπ(a022+n=1Nan2+bn2)=πn=N+1an2+bn20 \begin{align} \int_{-\pi}^{\pi} R_N^2(x) \, \text dx &= \int_{-\pi}^{\pi} (f(x) - S_N(x))^2 \, \text dx\\ &=\int_{-\pi}^{\pi} f^2(x)-2f(x)S_N(x)+S^2_N(x) \, \text dx \\ &=\int_{-\pi}^{\pi} f^2(x) \, \text dx -2 \left ( \frac{2 \pi \cdot a^2_0}{4} + \pi \cdot \sum_{n=1}^{N} a^2_n + b^2_n \right ) + \left ( \frac{2\pi \cdot a^2_0}{4} + \pi \cdot \sum_{n=1}^{N} a^2_n + b^2_n \right ) \\ &=\int_{-\pi}^{\pi} f^2(x) \, \text dx - \left ( \frac{2\pi \cdot a^2_0}{4} + \pi \cdot \sum_{n=1}^{N} a^2_n + b^2_n \right ) \\ &=\int_{-\pi}^{\pi} f^2(x) \, \text dx - \pi \left ( \frac{ a^2_0}{2} + \sum_{n=1}^{N} a^2_n + b^2_n \right ) \\ &=\pi \cdot \sum_{n=N+1}^{\infty} a^2_n + b^2_n \geqslant 0 \end{align}

因为贝塞尔不等式成立 如果 f(x)f(x) 可积 limnan,bn=0,0\to \lim_{n \to \infty}a_n,b_n = 0,0

黎曼引理的另一种证明方式

limn+0πf(x)sin(n+12)xdx=0limn+0πf(x)sinnxdx=0把积分补齐 0πππlimn+ππf(x)sinnxdx=limn+bn=0\begin{align*} \lim_{n \to +\infty} \int_0^\pi f(x) \sin \left(n + \frac{1}{2}\right) x \, \mathrm{d}x &= 0 \\ \Downarrow \\ \lim_{n \to +\infty} \int_0^\pi f(x) \sin nx \, \mathrm{d}x &= 0 \\ \Downarrow &\quad \text{把积分补齐 } \int_0^\pi \to \int_{-\pi}^\pi \\ \lim_{n \to +\infty} \int_{-\pi}^\pi f(x) \sin nx \, \mathrm{d}x &= \lim_{n \to +\infty} b_n = 0 \end{align*}

傅里叶级数收敛性的证明

SN(x)=a02+n=1N(ancosnx+bnsinnx)S_N(x)=\frac{a_{0}}{2}+\sum_{n = 1}^{N}(a_{n}\cos nx + b_{n}\sin nx)

a0,an,bna_0, a_n, b_n 带入:

a0=1πππf(x)dx,an=1πππf(x)cosnxdx,bn=1πππf(x)sinnxdxa_{0}=\frac{1}{\pi}\int_{-\pi}^{\pi}f(x)\,\text dx ,\quad a_{n}=\frac{1}{\pi}\int_{-\pi}^{\pi}f(x)\cos nx\,\text dx, \quad b_{n}=\frac{1}{\pi}\int_{-\pi}^{\pi}f(x)\sin nx\,\text dx

所以:

SN(x)=12πππf(x)dx+n=1N(1πππf(x)cosnxdxcosnx+1πππf(x)sinnxdxsinnx)S_N(x) = \frac{1}{2\pi}\int_{-\pi}^{\pi}f(x)\,\text dx + \sum_{n = 1}^{N}\left(\frac{1}{\pi}\int_{-\pi}^{\pi}f(x)\cos nx\,\text dx\cos nx + \frac{1}{\pi}\int_{-\pi}^{\pi}f(x)\sin nx\,\text dx \sin nx\right)

将积分中的变量用别的字母替代 xtx \to t

SN(x)=12πππf(t)dt+n=1N(1πππf(t)cosntdtcosnx+1πππf(t)sinntdxsinnx)S_N(x) = \frac{1}{2\pi}\int_{-\pi}^{\pi}f(t)\,\text dt + \sum_{n = 1}^{N }\left( \frac{1}{\pi}\int_{-\pi}^{\pi}f(t)\cos nt\,\text dt\cos nx + \frac{1}{\pi}\int_{-\pi}^{\pi}f(t)\sin nt\,\text dx \sin nx \right)

cosnx,sinnx\cos nx, \sin nx 放入积分内:

SN(x)=12πππf(t)dt+n=1N(1πππf(t)cosntcosnx dt+1πππf(t)sinntsinnxdt)S_N(x) = \frac{1}{2\pi}\int_{-\pi}^{\pi}f(t)\,\text dt + \sum_{n = 1}^{N }\left( \frac{1}{\pi}\int_{-\pi}^{\pi}f(t)\cos nt \cos nx \ \text dt + \frac{1}{\pi}\int_{-\pi}^{\pi}f(t)\sin nt \sin nx \,\text dt \right)

交换积分与求和顺序:

SN(x)=12πππf(t)dt+1πππn=1N(f(t)cosntcosnx+f(t)sinntsinnx)dtS_N(x) = \frac{1}{2\pi}\int_{-\pi}^{\pi}f(t)\,\text dt + \frac{1}{\pi} \int_{-\pi}^{\pi} \sum_{n = 1}^{N} \left( f(t)\cos nt \cos nx + f(t)\sin nt \sin nx \right) \text dt

合并 f(t)f(t)cosntcosnx\cos nt \cos nx, sinntsinnx\sin nt \sin nx

SN(x)=12πππf(t)dt+1πππn=1Nf(t)cosn(tx)dtS_N(x) = \frac{1}{2\pi}\int_{-\pi}^{\pi}f(t)\,\text dt + \frac{1}{\pi} \int_{-\pi}^{\pi} \sum_{n = 1}^{N} f(t) \cos n(t-x) \,\text dt

12πππf(t)dt\frac{1}{2\pi}\int_{-\pi}^{\pi}f(t)\,\text dt 拿进去,f(x)f(x) 拿出来:

SN(x)=1πππf(t)(12+n=1Ncosn(tx))dtS_N(x) = \frac{1}{\pi} \int_{-\pi}^{\pi} f(t) \left( \frac{1}{2} + \sum_{n = 1}^{N} \cos n(t-x) \right) \,\text dt

换元,令 tx=ut=u+xt-x=u \to t = u+x

SN(x)=1ππxπxf(u+x)(12+n=1Ncosnu)duS_N(x) = \frac{1}{\pi} \int_{-\pi-x}^{\pi-x} f(u+x) \left( \frac{1}{2} + \sum_{n = 1}^{N} \cos nu \right) \,\text du

因为 {cosnun1}\{\cos nu | n \ge 1\} 都是周期函数,所以 πxπxππ\int_{-\pi-x}^{\pi-x} \to \int_{-\pi}^{\pi}

SN(x)=1πππf(u+x)(12+n=1Ncosnu)duS_N(x) = \frac{1}{\pi} \int_{-\pi}^{\pi} f(u+x) \left( \frac{1}{2} + \sum_{n = 1}^{N} \cos nu \right) \,\text du

DN(x)D_N(x)

SN(x)=1πππf(u+x)sin(2N+1)u22sinu2duS_N(x) = \frac{1}{\pi} \int_{-\pi}^{\pi} f(u+x) \frac{\sin \frac{(2N+1)u}{2}}{2 \sin \frac{u}{2}} \,\text du

现在让 N+N \to +\infty, x=x0x = x_0

limN+SN(x0)=limN+1πππf(u+x0)sin(2N+1)u22sinu2du\lim_{N \to +\infty} S_N(x_0) = \lim_{N \to +\infty} \frac{1}{\pi} \int_{-\pi}^{\pi} f(u+x_0) \frac{\sin \frac{(2N+1)u}{2}}{2 \sin \frac{u}{2}} \,\text du

πππ0+0π\int_{-\pi}^{\pi} \to \int_{-\pi}^{0} + \int_{0}^{\pi}:

limN+SN(x0)=limN+1ππ0f(u+x0)sin(2N+1)u22sinu2du+limN+1π0πf(u+x0)sin(2N+1)u22sinu2du\lim_{N \to +\infty} S_N(x_0) = \lim_{N \to +\infty} \frac{1}{\pi} \int_{-\pi}^{0} f(u+x_0) \frac{\sin \frac{(2N+1)u}{2}}{2 \sin \frac{u}{2}} \,\text du + \lim_{N \to +\infty} \frac{1}{\pi} \int_{0}^{\pi} f(u+x_0) \frac{\sin \frac{(2N+1)u}{2}}{2 \sin \frac{u}{2}} \,\text du

[π,0][-\pi,0]u=v-u = v

limN+SN(x0)=limN+1π0πf(v+x0)sin(2N+1)v22sinv2dv+limN+1π0πf(u+x0)sin(2N+1)u22sinu2du\lim_{N \to +\infty} S_N(x_0) = \lim_{N \to +\infty} \frac{1}{\pi} \int_{0}^{\pi} f(-v+x_0) \frac{\sin \frac{(2N+1)v}{2}}{2 \sin \frac{v}{2}} \,\text dv + \lim_{N \to +\infty} \frac{1}{\pi} \int_{0}^{\pi} f(u+x_0) \frac{\sin \frac{(2N+1)u}{2}}{2 \sin \frac{u}{2}} \,\text du

合并 u,vtu, v \to t

limN+SN(x0)=limN+1π0π(f(x0+t)+f(x0t))sin(2N+1)t22sint2dt\begin{align} \lim_{N \to +\infty} S_N(x_0) = \lim_{N \to +\infty} \frac{1}{\pi} \int_{0}^{\pi} \left( f(x_0+t) + f(x_0-t) \right) \frac{\sin \frac{(2N+1)t}{2}}{2 \sin \frac{t}{2}} \,\text dt \end{align}

同时减去 s=f+(x0)+f(x0)2s = \frac{f_+(x_0) + f_-(x_0)}{2},其中 ssf(x0)f(x_0) 的左右极限除以 2:

limN+SN(x0)f+(x0)+f(x0)2=limN+1π0π(f(x0+t)+f(x0t)f+(x0)f(x0))sin(2N+1)t22sint2dt\begin{align} &\lim_{N \to +\infty} S_N(x_0) - \frac{f_+(x_0) + f_-(x_0)}{2} =\\ &\lim_{N \to +\infty} \frac{1}{\pi} \int_{0}^{\pi} \left( f(x_0+t) + f(x_0-t) - f_+(x_0) - f_-(x_0) \right) \frac{\sin \frac{(2N+1)t}{2}}{2 \sin \frac{t}{2}} \,\text dt \end{align}

0π=0δ+δπ\int_{0}^{\pi} = \int_{0}^{\delta} + \int_{\delta}^{\pi}:

limδ0+limN+SN(x0)s=limN+1π0δf(x0+t)+f(x0t)f+(x0)f(x0)sin(2N+1)t22sint2dt+1πδπ(f(x0+t)+f(x0t)2s)2sint2sin(2N+1)t2dt\begin{align} \lim_{\delta \to 0^+} \lim_{N \to +\infty} S_N(x_0) - s &=\\ \lim_{N \to +\infty} \frac{1}{\pi} &\int_{0}^{\delta} f(x_0+t) + f(x_0-t) - f_+(x_0) - f_-(x_0) \frac{\sin \frac{(2N+1)t}{2}}{2 \sin \frac{t}{2}} \,\text dt + \\ \frac{1}{\pi} &\int_{\delta}^{\pi} \frac{\left( f(x_0+t) + f(x_0-t) - 2s \right)}{2 \sin \frac{t}{2}} \sin \frac{(2N+1)t}{2} \,\text dt \end{align}

由于 δπ=0\int_{\delta}^{\pi} = 0:

limδ0+limN+SN(x0)s=limδ0+limN+1π0δ(f(x0+t)f+(x0)+f(x0t)f(x0))tsin(n+12)tdt\begin{align} &\lim_{\delta \to 0^+} \lim_{N \to +\infty} S_N(x_0) - s = \\ &\lim_{\delta \to 0^+} \lim_{N \to +\infty} \frac{1}{\pi} \int_{0}^{\delta} \frac{\left( f(x_0+t) - f_+(x_0) + f(x_0-t) - f_-(x_0) \right)}{t} \sin \left( n + \frac{1}{2} \right) t \,\text dt \end{align}

由于 f(x)f(x) 可积
或者说 0πf(x0+t)f+(x0)+f(x0t)f(x0)tdt\int_{0}^{\pi} \frac{f(x_0+t) - f_+(x_0) + f(x_0-t) - f_-(x_0)}{t} \,\text dt 收敛
或者 limδ0+0δf(x0+t)f+(x0)+f(x0t)f(x0)tdt=0\lim_{\delta \to 0^+} \int_{0}^{\delta} \frac{f(x_0+t) - f_+(x_0) + f(x_0-t) - f_-(x_0)}{t} \,\text dt = 0:

limN+SN(x0)s=0\lim_{N \to +\infty} S_N(x_0) - s = 0

最终得出结论:

limN+SN(x0)=f+(x0)+f(x0)2\lim_{N \to +\infty} S_N(x_0) = \frac{f_+(x_0) + f_-(x_0)}{2}

欧拉公式

eiθ=cosθ+isinθe^{i\theta}=\cos\theta + i\sin\theta

根据欧拉公式 eiθ=cosθ+isinθe^{i\theta}=\cos\theta + i\sin\theta,我们可以对其进行变形来得到 cosθ\cos\thetasinθ\sin\theta 的表达式。
已知 eiθ=cosθ+isinθe^{i\theta}=\cos\theta + i\sin\theta,同时 eiθ=cos(θ)+isin(θ)=cosθisinθe^{-i\theta}=\cos(-\theta)+i\sin(-\theta)=\cos\theta - i\sin\theta

cosθ=eiθ+eiθ2sinθ=eiθeiθ2icosnθ=einθ+einθ2sinnθ=einθeinθ2i\begin{align} \cos\theta&=\frac{e^{i\theta}+e^{-i\theta}}{2} \\ \sin\theta&=\frac{e^{i\theta}-e^{-i\theta}}{2i} \\ \cos n\theta&=\frac{e^{in\theta}+e^{-in\theta}}{2} \\ \sin n\theta&=\frac{e^{in\theta}-e^{-in\theta}}{2i} \end{align}

傅里叶级数的复数表示

cosnθ,sinnθ\cos n\theta, \sin n\theta 带入傅里叶级数:

f(θ)=a02+n=1(aneinθ+einθ2+bneinθeinθ2i)f(\theta) = \frac{a_0}{2} + \sum_{n=1}^{\infty} \left( a_n \frac{e^{in\theta}+e^{-in\theta}}{2} + b_n \frac{e^{in\theta}-e^{-in\theta}}{2i} \right)

合并 einθ,einθe^{in\theta}, e^{-in\theta} 的系数 :

f(θ)=a02+n=1(anibn2einθ+an+ibn2einθ)f(\theta) = \frac{a_0}{2} + \sum_{n=1}^{\infty} \left( \frac{a_n-ib_n}{2} e^{in\theta} + \frac{a_n+ib_n}{2} e^{-in\theta} \right)

合并 \sum

f(θ)=n=+anibn2einθf(\theta) = \sum_{n=-\infty}^{+\infty} \frac{a_n-ib_n}{2} e^{in\theta}

cnc_n 的复数表示:

cn=anibn2=12πππf(x)(cosnxisinnx)dx=12πππf(x)einxdxc_n = \frac{a_n-ib_n}{2}= \frac{1}{2\pi} \int_{-\pi}^{\pi} f(x) (\cos nx-i\sin nx) \,\text{d}x = \frac{1}{2\pi} \int_{-\pi}^{\pi} f(x) e^{-inx} \,\text{d}x

傅里叶级数的复数表示:

f(θ)=n=+cneinθf(\theta) = \sum_{n=-\infty}^{+\infty} c_n e^{in\theta}

周期为T的傅里叶级数的复数表示

f(t)=n=cnei2πTnt\begin{align} f(t) &= \sum_{n=-\infty}^{\infty} c_n e^{i \frac{2\pi}{T} n t} \\ \end{align}

an,bna_n, b_n :

f(t)=a02+n=1N(ancos2πTnt+bnsin2πTnt)0Tf(t)cos2πTntdt=an0Tcos22πTntdt=anT2an=2T0Tf(t)cos2πTntdt\begin{align} f(t)&=\frac{a_{0}}{2}+\sum_{n = 1}^{N}(a_{n}\cos \frac{2\pi}{T} nt + b_{n}\sin \frac{2\pi}{T} nt) \\ \int_0^{T} f(t) \cos \frac{2\pi}{T} nt \,\text{d}t &= a_n\int_0^{T} \cos^2 \frac{2\pi}{T} nt \,\text{d}t =a_n \frac{T}{2} \\ a_n &= \frac{2}{T} \int_0^{T} f(t) \cos \frac{2\pi}{T} nt \,\text{d}t \end{align}

cnc_n 的复数表示:

cn=anibn2=1T0Tf(t)(cos2πTntisin2πTnt)dt=1T0Tf(t)ei2πTntdtc_n = \frac{a_n-ib_n}{2}= \frac{1}{T} \int_{0}^{T} f(t) (\cos \frac{2\pi}{T} nt - i\sin \frac{2\pi}{T} nt) \,\text{d}t = \frac{1}{T} \int_{0}^{T} f(t) e^{-i \frac{2\pi}{T} nt} \,\text{d}t

e 形式的正交基

要判断一组复指数函数是否正交,我们可以考虑以下形式的函数:

ei2πTnte^{i\frac{2\pi}{T} nt}

其中 nnmm 是不同的整数。为了判断 ei2πTnte^{i\frac{2\pi}{T} nt}ei2πTmte^{i\frac{2\pi}{T} mt} 的正交性,我们需要计算它们在一个周期 TT 内的内积:

0Tei2πTntei2πTmtdt=0Tei2πT(nm)tdt\int_0^T e^{i\frac{2\pi}{T} nt} \cdot \overline{e^{i\frac{2\pi}{T} mt}} \, dt = \int_0^T e^{i\frac{2\pi}{T} (n-m)t} \, dt

计算这个积分:

n=mn = m 时:

0Tei2πT(nm)tdt=0T1dt=T\int_0^T e^{i\frac{2\pi}{T} (n-m)t} \, dt = \int_0^T 1 \, dt = T

nmn \neq m 时:

0Tei2πT(nm)tdt=[1i2πT(nm)ei2πT(nm)t]0T=1i2πT(nm)(ei2π(nm)1)=1i2πT(nm)(11)=0\begin{align} \int_0^T e^{i\frac{2\pi}{T} (n-m)t} \, dt &= \left[ \frac{1}{i\frac{2\pi}{T} (n-m)} e^{i\frac{2\pi}{T} (n-m)t} \right]_0^T \\ &= \frac{1}{i\frac{2\pi}{T} (n-m)} \left( e^{i2\pi(n-m)} - 1 \right) \\ &= \frac{1}{i\frac{2\pi}{T} (n-m)} (1 - 1) = 0 \end{align}

连续傅里叶变换

从离散到连续,我们考虑 f(t)f(t) 是一个非周期信号,即周期 TT \to \infty。在这种情况下,傅里叶级数变成傅里叶变换。具体做法是将离散的频率分量变为连续的频率分量。

频率分量的连续化

为了将傅里叶级数的频率分量从离散变为连续,我们用 ω=nω0\omega = n \omega_0 替换 nn。注意到 ω0=2πT\omega_0 = \frac{2\pi}{T},当 TT \to \infty 时,ω00\omega_0 \to 0,频率分量变得连续。

所以,我们有: ω=nω0=n2πT\omega = n \omega_0 = n \frac{2\pi}{T}

这时,傅里叶系数 cnc_n 可以表示为: cn=1T0Tf(t)einω0tdtc_n = \frac{1}{T} \int_{0}^{T} f(t) e^{-i n \omega_0 t} \, dt 由于 ω=nω0\omega = n \omega_0,我们可以改写为:

c(2πnT)=c(ω)=1T0Tf(t)eiωtdtc \left(\frac{2\pi n}{T} \right) = c(\omega) = \frac{1}{T} \int_{0}^{T} f(t) e^{-i \omega t} \, dt

极限过程

TT \to \infty 时,ω00\omega_0 \to 0,频率分量变得连续。我们可以将傅里叶系数 cnc_n 变为傅里叶变换中的连续频谱 F(ω)F(\omega)

考虑到 ω\omega 是连续的,我们需要引入一个密度函数来替代 cnc_n。傅里叶系数 cnc_n 的表达式变为:

c(ω)=1TT2T2f(t)eiωtdtc(\omega) = \frac{1}{T} \int_{-\frac{T}{2}}^{\frac{T}{2}} f(t) e^{-i \omega t} \, dt

TT \to \infty 时,这个积分的上下限变为 -\infty\infty,所以我们得到傅里叶变换的公式:

F(ω)=f(t)eiωtdtF(\omega) = \int_{-\infty}^{\infty} f(t) e^{-i \omega t} \, dt

连续傅里叶逆变换

傅里叶级数的逆变换公式为:

f(t)=n=cneinω0tf(t) = \sum_{n=-\infty}^{\infty} c_n e^{i n \omega_0 t}

TT \to \infty 时,离散的和 (sum) 变为积分 (integral),并且 cnc_n 变为 F(ω)F(\omega)

f(t)=12πn=2πTF(ω)eiωtf(t)=12πF(ω)eiωtdω\begin{align} f(t) &= \frac{1}{2\pi} \sum_{n=-\infty}^{\infty} \frac{2\pi}{T} F(\omega) e^{i \omega t} \\ f(t) &= \frac{1}{2\pi} \int_{-\infty}^{\infty} F(\omega) e^{i \omega t} \, d\omega \end{align}

通过将傅里叶级数的周期 TT 取到无限大,我们可以将离散的频率分量变为连续的频率分量,从而推导出傅里叶变换。这展示了傅里叶级数和傅里叶变换在处理周期性和非周期性信号时的内在联系。

离散傅里叶变换

对于周期信号 x[n]x[n],我们可以使用傅里叶级数来表示它:

x[n]=k=0N1X[k]ei2πNknx[n] = \sum_{k=0}^{N-1} X[k] \cdot e^{i \frac{2\pi}{N} kn}

其中 X[k]X[k] 是傅里叶系数。

复指数函数的正交性

n=0N1ei2πN(mk)n={N,if m=k0,if mk\begin{align} \sum_{n=0}^{N-1} e^{i \frac{2\pi}{N} (m-k)n} = \begin{cases} N, & \text{if } m = k \\ 0, & \text{if } m \ne k \end{cases} \end{align}

离散傅里叶变换系数

为了找到傅里叶变换系数 X[k]X[k],我们将上述傅里叶级数公式两边乘以 ei2πNkne^{-i \frac{2\pi}{N} kn} 并对 nn 求和:

n=0N1x[n]ei2πNkn=n=0N1(m=0N1X[m]ei2πNmn)ei2πNkn\sum_{n=0}^{N-1} x[n] \cdot e^{-i \frac{2\pi}{N} kn} = \sum_{n=0}^{N-1} \left( \sum_{m=0}^{N-1} X[m] \cdot e^{i \frac{2\pi}{N} mn} \right) \cdot e^{-i \frac{2\pi}{N} kn}

交换求和次序:

n=0N1x[n]ei2πNkn=m=0N1X[m](n=0N1ei2πN(mk)n)\sum_{n=0}^{N-1} x[n] \cdot e^{-i \frac{2\pi}{N} kn} = \sum_{m=0}^{N-1} X[m] \left( \sum_{n=0}^{N-1} e^{i \frac{2\pi}{N} (m-k)n} \right)

这样 k=0,1,2,3k=0,1,2,3 \cdots 代入上式

n=0N1x[n]ei2πNkn=X[k]N\sum_{n=0}^{N-1} x[n] \cdot e^{-i \frac{2\pi}{N} kn} = X[k] \cdot N

离散傅里叶逆变换

DFT:

X[k]=n=0N1x[n]ei2πNknX[k] = \sum_{n=0}^{N-1} x[n] \cdot e^{-i \frac{2\pi}{N} kn}

IDFT:

x[n]=1Nk=0N1X[k]ei2πNknx[n] = \frac{1}{N} \sum_{k=0}^{N-1} X[k] \cdot e^{i \frac{2\pi}{N} kn}

离散傅里叶变换可以用矩阵形式来表示,这种表示方式在计算机实现中非常有用,因为它将DFT视为矩阵与向量的乘积。

离散傅里叶变换矩阵

假设我们有一个长度为 NN 的离散序列 x=[x[0],x[1],,x[N1]]T\mathbf{x} = [x[0], x[1], \ldots, x[N-1]]^T。DFT 可以表示为矩阵乘法:

X=WNx\mathbf{X} = \mathbf{W}_N \cdot \mathbf{x}

其中:

  • X=[X[0],X[1],,X[N1]]T\mathbf{X} = [X[0], X[1], \ldots, X[N-1]]^T 是频域表示的结果向量。
  • WN\mathbf{W}_NN×NN \times N 的DFT矩阵。

DFT 矩阵 WN\mathbf{W}_N 的元素由以下公式给出:

WN[k,n]=ei2πNknW_{N}[k, n] = e^{-i \frac{2\pi}{N} kn}

其中 k,n=0,1,2,,N1k, n = 0, 1, 2, \ldots, N-1。具体来说,矩阵 WN\mathbf{W}_N 的第 kk 行,第 nn 列的元素是:

WN[k,n]=cos(2πNkn)isin(2πNkn)W_{N}[k, n] = \cos\left(\frac{2\pi}{N} kn\right) - i \sin\left(\frac{2\pi}{N} kn\right)

由此可知当n为偶数时, WN[k,n]=WN[k+N2,n]W_{N}[k, n]=W_N[k+\frac{N}{2},n]

矩阵形式的DFT计算

将信号 x\mathbf{x} 与 DFT 矩阵 WN\mathbf{W}_N 相乘,即可得到频域表示 X\mathbf{X}

X=[11111WW2WN11W2W4W2(N1)1WN1W2(N1)W(N1)(N1)][x[0]x[1]x[2]x[N1]]\mathbf{X} = \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 \\ 1 & W & W^2 & \cdots & W^{N-1} \\ 1 & W^2 & W^4 & \cdots & W^{2(N-1)} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & W^{N-1} & W^{2(N-1)} & \cdots & W^{(N-1)(N-1)} \end{bmatrix} \begin{bmatrix} x[0] \\ x[1] \\ x[2] \\ \vdots \\ x[N-1] \end{bmatrix}

其中 W=ei2πNW = e^{-i \frac{2\pi}{N}} 是单位根。

逆离散傅里叶变换矩阵

逆离散傅里叶变换也可以用矩阵形式表示,其矩阵 WN\mathbf{W}_N^* 是DFT矩阵的共轭转置,并且需要乘以 1N\frac{1}{N}

x=1NWNX\mathbf{x} = \frac{1}{N} \mathbf{W}_N^* \cdot \mathbf{X}

其中 WN\mathbf{W}_N^* 的元素为:

WN[k,n]=ei2πNknW_{N}^*[k, n] = e^{i \frac{2\pi}{N} kn}

快速傅里叶变换

快速傅里叶变换是一种 求解离散傅里叶变换的 算法

离散傅里叶变换

X[k]=n=0N1x[n]ei2πNknX[k] = \sum_{n=0}^{N-1} x[n] \cdot e^{-i \frac{2\pi}{N} kn}

利用 ei2πNkne^{−i\frac{2π}{N}kn} 的周期性,通过观察可以发现,当nn为偶数时(我们用2n2n表示)

ei2πNk 2n=ei2πN2kn=ei2πN2(k+N2)ne^{−i\frac{2π}{N}k\ 2n}=e^{−i\frac{2π}{\frac{N}{2}}kn}=e^{−i\frac{2π}{\frac{N}{2}}(k+\frac{N}{2})n}

由此可知当n为偶数时

WN[k,n]=WN[k+N2,n]W_{N}[k, n]=W_N[k+\frac{N}{2},n]

nn为奇数时,我们可以提取一个 ei2πNke^{−i\frac{2π}{N}k} 公因数,让剩下的 WN[k,n]W_{N}[k, n] 满足nn为偶数的条件。

将 X[k]X[k] 分为 nn 为偶数以及 nn 为奇数两个部分。

X[k]=n=0N21x[2n]ei2πNk2n+n=0N21x[2n+1]ei2πNk(2n+1)=n=0N21x[2n]ei2πNk2n+ei2πNkn=0N21x[2n+1]ei2πNk2n=n=0N21x[2n]ei2πN2kn+ei2πNkn=0N21x[2n+1]ei2πN2kn=n=0N21x[2n]WN[k,2n]+ei2πNkn=0N21x[2n+1]WN[k,2n]=n=0N21x[2n]WN2[k,n]+ei2πNkn=0N21x[2n+1]WN2[k,n]\begin{align} X[k]&=\sum_{n=0}^{\frac{N}{2}−1}x[2n]e^{-i \frac{2\pi}{N} k2n} + \sum_{n=0}^{\frac{N}{2}−1}x[2n+1]e^{-i \frac{2\pi}{N} k(2n+1)} \\ &=\sum_{n=0}^{\frac{N}{2}−1}x[2n]e^{-i \frac{2\pi}{N} k2n}+e^{i \frac{2\pi}{N} k}\sum_{n=0}^{\frac{N}{2}−1}x[2n+1]e^{-i \frac{2\pi}{N} k2n} \\ &=\sum_{n=0}^{\frac{N}{2}−1}x[2n]e^{-i \frac{2\pi}{\frac{N}{2}} kn}+e^{-i \frac{2\pi}{N} k}\sum_{n=0}^{\frac{N}{2}−1}x[2n+1]e^{-i \frac{2\pi}{\frac{N}{2}} kn} \\ &=\sum_{n=0}^{\frac{N}{2}−1}x[2n]W_{N}[k, 2n]+e^{-i \frac{2\pi}{N} k}\sum_{n=0}^{\frac{N}{2}−1}x[2n+1]W_{N}[k, 2n] \\ &=\sum_{n=0}^{\frac{N}{2}−1}x[2n]W_{\frac{N}{2}}[k, n]+e^{-i \frac{2\pi}{N} k}\sum_{n=0}^{\frac{N}{2}−1}x[2n+1]W_{\frac{N}{2}}[k, n] \\ \end{align}

我们令偶数部分为 E[k]E[k] ,奇数部分提取公因数后的部分为 O[k]O[k] ,则 

X[k]=E[k]+WN[k,1]O[k]X[k]=E[k]+W_N[k,1]O[k]

对于上式 k<N2k \lt \frac{N}{2} 成立,当 N2k<N\frac{N}{2} \leqslant k \lt N 反转一圈

WN2[k,n]=WN2[k+N2,n]W_{\frac{N}{2}}[k, n]=W_{\frac{N}{2}}\left[k+\frac{N}{2},n\right]

WN[k,1]W_N[k,1]反转半圈,相当于取反

WN[k+N2,1]=WN[k,1]W_N\left[k+\frac{N}{2},1\right]=-W_N[k,1]

快速傅里叶变换公式 k<N2k \lt \frac{N}{2}

X[k]=E[k]+WN[k,1]O[k]X[k+N2]=E[k]WN[k,1]O[k]\begin{align} X[k]&=E[k]+W_N[k,1]O[k] \\ X\left[k+\frac{N}{2}\right]&=E[k]−W_N[k,1]O[k] \end{align}

代码实现

import cmath

def fft(x):
    N = len(x)
    if N <= 1:
        return x
    elif N % 2 != 0:
        raise ValueError("Size of x must be a power of 2")

    # FFT of even and odd indexed elements
    even = fft(x[0::2])
    odd = fft(x[1::2])

    # Combine
    T = [cmath.exp(-2j * cmath.pi * k / N) * odd[k] for k in range(N // 2)]
    return [even[k] + T[k] for k in range(N // 2)] + \
           [even[k] - T[k] for k in range(N // 2)]

# 示例数据
x = [0, 1, 0, -1]
result = fft(x)
for i, val in enumerate(result):
    print(f"X[{i}] = {val}")

时间复杂度

T(N)=2T(N2)+N=2(2T(N4)+N2)+N=2(2(2T(N8)+N4)+N2)+N=2log2NT(1)+Nlog2N\begin{align} T(N)&=2T\left(\frac{N}{2}\right)+N \\ &=2\left(2T\left(\frac{N}{4}\right)+\frac{N}{2}\right)+N \\ &=2\left(2\left(2T\left(\frac{N}{8}\right)+\frac{N}{4}\right)+\frac{N}{2}\right)+N \\ &=2\log_2NT(1)+N\log_2N\\ \end{align}

分解到最后只有一项,只需要进行一次乘法运算即可。所以T(1)=1T(1)=1

T(N)=N(log2N+1)T(N)=N(\log_2N+1)

多项式与快速傅里叶变换

A(x)=apxp+ap1xp1++a0B(x)=bqxq+bq1xq1++b0C(x)=A(x)B(x)=crxr+cr1xr1++c0 \begin{align} A(x) &= a_px^p+a_{p-1}x^{p-1}+\cdots+a_0\\ B(x) &= b_qx^q+b_{q-1}x^{q-1}+\cdots+b_0 \\ C(x) &= A(x) \, B(x)= c_{r}x^{r}+c_{r-1}x^{r-1}+\cdots+c_0\ \end{align}

用时间复杂度 O(Nlog2N)O(N \cdot \log_2N) 求解 crc_r 需要三步骤

应用快速傅里叶变换转换到点值表示

对于多项式 A(x)=anxn+an1xn1++a0A(x) = a_nx^n+a_{n-1}x^{n-1}+\cdots+a_0 选出大于 p+qp+q 的最小的 2 的幂次 NN 。 对 A(x),B(x)A(x),B(x) 分别做快速傅里叶变换

[A[0]A[1]A[2]A[N1]]=[11111WW2WN11W2W4W2(N1)1WN1W2(N1)W(N1)(N1)][a0a1a2aN1]\begin{bmatrix} A[0] \\ A[1] \\ A[2] \\ \vdots \\ A[N-1] \end{bmatrix} = \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 \\ 1 & W & W^2 & \cdots & W^{N-1} \\ 1 & W^2 & W^4 & \cdots & W^{2(N-1)} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & W^{N-1} & W^{2(N-1)} & \cdots & W^{(N-1)(N-1)} \end{bmatrix} \begin{bmatrix} a_0 \\ a_1 \\ a_2 \\ \vdots \\ a_{N-1} \end{bmatrix}
[B[0]B[1]B[2]B[N1]]=[11111WW2WN11W2W4W2(N1)1WN1W2(N1)W(N1)(N1)][b0b1b2bN1]\begin{bmatrix} B[0] \\ B[1] \\ B[2] \\ \vdots \\ B[N-1] \end{bmatrix} = \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 \\ 1 & W & W^2 & \cdots & W^{N-1} \\ 1 & W^2 & W^4 & \cdots & W^{2(N-1)} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & W^{N-1} & W^{2(N-1)} & \cdots & W^{(N-1)(N-1)} \end{bmatrix} \begin{bmatrix} b_0 \\ b_1 \\ b_2 \\ \vdots \\ b_{N-1} \end{bmatrix}

逐点相乘

C[n]=A[n]B[n]C[n] = A[n] \cdot B[n]

逆快速傅里叶转换回系数表示

[c0c1c2cN1]=1N[11111W1W2W(N1)1W2W4W2(N1)1W(N1)W2(N1)W(N1)(N1)][C[0]C[1]C[2]C[N1]]\begin{bmatrix} c_0 \\ c_1 \\ c_2 \\ \vdots \\ c_{N-1} \end{bmatrix} = \frac{1}{N} \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 \\ 1 & W^{-1} & W^{-2} & \cdots & W^{-(N-1)} \\ 1 & W^{-2} & W^{-4} & \cdots & W^{-2(N-1)} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & W^{-(N-1)} & W^{-2(N-1)} & \cdots & W^{-(N-1)(N-1)} \end{bmatrix} \begin{bmatrix} C[0] \\ C[1] \\ C[2] \\ \vdots \\ C[N-1] \end{bmatrix}

代码实现

import cmath


def fft(x):
    N = len(x)
    if N <= 1:
        return x
    elif N % 2 != 0:
        raise ValueError("Size of x must be a power of 2")

    # FFT of even and odd indexed elements
    even = fft(x[0::2])
    odd = fft(x[1::2])

    # Combine
    T = [cmath.exp(-2j * cmath.pi * k / N) * odd[k] for k in range(N // 2)]
    return [even[k] + T[k] for k in range(N // 2)] + [
        even[k] - T[k] for k in range(N // 2)
    ]


def ifft(x):
    N = len(x)
    if N <= 1:
        return x
    elif N % 2 != 0:
        raise ValueError("Size of x must be a power of 2")

    # FFT of even and odd indexed elements
    even = ifft(x[0::2])
    odd = ifft(x[1::2])

    # Combine
    T = [cmath.exp(2j * cmath.pi * k / N) * odd[k] for k in range(N // 2)]
    return [even[k] + T[k] for k in range(N // 2)] + [
        even[k] - T[k] for k in range(N // 2)
    ]


def next_power_of_two(x):
    return 1 if x == 0 else 2 ** (x - 1).bit_length()


def round_and_convert(C, n, m):
    # 初始化结果列表
    result = []

    # 遍历复数数组 C
    for c in C:
        # 取复数的实部,四舍五入并转换为整数
        rounded_int = float(f"{c.real:.4f}")
        # 将结果添加到列表中
        result.append(rounded_int)

    # 返回结果列表的前n+m-1个元素
    return result[: n + m - 1]


def fft_multiply(A, B):
    # 确定输出多项式的长度
    n = len(A)
    m = len(B)
    N = next_power_of_two(n + m - 1)

    # 将 A 和 B 扩展到长度 N
    A.extend([0] * (N - n))
    B.extend([0] * (N - m))

    # 应用 FFT
    A_fft = fft(A)
    B_fft = fft(B)

    # 逐点相乘
    C_fft = [A_fft[i] * B_fft[i] for i in range(N)]

    # 应用逆 FFT
    C = [i / N for i in ifft(C_fft)]

    # 由于数值误差,结果可能是复数,取实部并四舍五入
    return round_and_convert(C, n, m)


# # 示例多项式
A = [1.5, 2, 3]  # 表示多项式 1.5 + 2x + 3x^2
B = [4, 5.3, 6]  # 表示多项式 4 + 5.3x + 6x^2
C = fft_multiply(A, B)
print(C) # [6.0, 15.95, 31.6, 27.9, 18.0]