快速傅里叶变换(FFT)和逆快速傅里叶变换(IFFT)
多项式表示法与卷积
多项式有两种表示方法
- 系数表示法
- 点值表示法
系数表示法
就是最普通的表示方法,如
f(x)=a0x0+a1x1+a2x2+......+an−1xn−1f(x) = a_0x^0 + a_1x^1 + a_2x^2 + ...... + a_{n-1}x^{n-1} f(x)=a0x0+a1x1+a2x2+......+an−1xn−1则表示为 f(x)={a0,a1,a2,......,an−1}f(x) = \{a_0, a_1, a_2, ......, a_{n-1}\}f(x)={a0,a1,a2,......,an−1}
点值表示法
用平面坐标系上的点来描述多项式的一种表示方法
对于一个多项式来说有 n 项,则可以通过 n 对 {x,y}\{x, y\}{x,y} 点对来进行系数求解,即对于上述式子来说还有
f(x)={(x0,f(x0)),(x1,f(x1)),(x2,f(x2)),......,(xn−1,f(xn−1))}f(x) = \{(x_0, f(x_0)), (x_1, f(x_1)), (x_2, f(x_2)), ......, (x_{n-1}, f(x_{n-1}))\} f(x)={(x0,f(x0)),(x1,f(x1)),(x2,f(x2)),......,(xn−1,f(xn−1))}这种表达方式
卷积
就是多项式相乘,对于2种不同的多项式表示法来说,做卷积的时间复杂度会不同
- 系数表示法,由于每2个系数之间都需要做一次处理,所以时间复杂度需要 O(n2)
- 点值表示法,只要对应的两个点的 f(xi)f(x_i)f(xi) 相乘即可,所以时间复杂度只有 O(n)
但是将系数表示法转换成点值表示法,如果用朴素的转换方法,也需要 O(n2) 的时间复杂度,所以采取DFT通过分治法来做
离散傅里叶变换(DFT)
傅里叶变换中所有的 n 都为 2 的整数次幂
我们的目标是将系数表示法转换成点值表示法,如果随机选取 nnn 个点,再计算出它对应的 f(x)f(x)f(x),时间复杂度为 O(n2),因为对每个点都需要求 nnn 个 xi,i∈[0,n−1]x^i, i∈[0, n - 1]xi,i∈[0,n−1]
傅里叶选取了一些点,这些点满足它们的若干次方 = 1,这样可以使得带入之后不需要做这么多运算(但是时间复杂度仍是O(n2))
这些点都在复数平面直角坐标系里
圆上所有的点都满足傅里叶的要求
我们假设将其 n=8n = 8n=8 等分,则会得到:
从 (1,0)(1, 0)(1,0) 按照逆时针进行编号,对于编号为 k 的点,记为 wnkw_n^kwnk,称为 nnn 次单位根,且
wnk=coskn2π+isinkn2πw_n^k = \cos{\frac{k}{n}2\pi} + i\sin{\frac{k}{n}2\pi} wnk=cosnk2π+isinnk2π
单位根的性质
- wnk=w2n2kw_n^k = w_{2n}^{2k}wnk=w2n2k,2可以替换为任意整数
- wnk+n2w_n^{k+\frac{n}{2}}wnk+2n = −wnk-w_n^k−wnk
- wn0=wnnw_n^0 = w_n^nwn0=wnn
- 对任意 k∈[0,n]k∈[0, n]k∈[0,n],有 Σj=0n−1(wnk)j=0\Sigma_{j=0}^{n-1}(w_n^k)^j = 0Σj=0n−1(wnk)j=0
快速傅里叶变换(FFT)
简介
虽然通过DFT选出了便于计算的点,但是时间复杂度仍为 O(n2),但是通过分析多项式可以得到用分治法处理这些点的方式。
假设有
A(x)=Σj=0n−1aixi=a0+a1x1+a2x2+......+an−1xn−1A(x) = \Sigma_{j=0}^{n-1}a_ix^i = a_0 + a_1x^1 + a_2x^2 + ...... + a_{n-1}x^{n-1} A(x)=Σj=0n−1aixi=a0+a1x1+a2x2+......+an−1xn−1现在将 A(x)A(x)A(x) 中 xxx 的下标奇偶性将 A(x)A(x)A(x) 分成两部分
A(x)=(a0+a2x2+a4x4+......+an−2xn−2)+x(a1+a3x2+......+an−1xn−2)A(x) = (a_0 + a_2x^2 + a_4x^4 + ...... + a_{n-2}x^{n-2}) + x(a_1 + a_3x^2 + ...... + a_{n-1}x^{n-2}) A(x)=(a0+a2x2+a4x4+......+an−2xn−2)+x(a1+a3x2+......+an−1xn−2)所以有
A(x)=A1(x2)+xA2(x2)A(x) = A_1(x^2) + xA_2(x^2) A(x)=A1(x2)+xA2(x2)
当 k<n2k < \frac{n}{2}k<2n 的时候,将wnkw_n^kwnk 作为 xxx 带入 A(x)A(x)A(x)
A(wnk)=A1((wnk)2)+xA2((wnk)2)=A1(wn2k)+xA2(wn2k)=A1(wn2k)+wnkA2(wn2k)\begin {aligned} A(w_n^k) &= A_1((w_n^k)^2) + xA_2((w_n^k)^2) \\ &= A_1(w_n^{2k}) + xA_2(w_n^{2k}) \\ &=A_1(w_{\frac{n}{2}}^k) + w_n^kA_2(w_{\frac{n}{2}}^k) \end {aligned} A(wnk)=A1((wnk)2)+xA2((wnk)2)=A1(wn2k)+xA2(wn2k)=A1(w2nk)+wnkA2(w2nk)
所以当取后半部分的时候,有x=wnk+n2x = w_n^{k+\frac{n}{2}}x=wnk+2n
A(wnk+n2)=A1((wnk+n2)2)+xA2((wnk+n2)2)=A1(wn2kwnn)+wnk+n2A2(wn2kwnn)=A1(wn2k)−wnkA2(wn2k)=A1(wn2k)−wnkA2(wn2k)\begin {aligned} A(w_n^{k+\frac{n}{2}}) &= A_1((w_n^{k+\frac{n}{2}})^2) + xA_2((w_n^{k+\frac{n}{2}})^2) \\ &= A_1(w_n^{2k}w_n^n) + w_n^{k+\frac{n}{2}}A_2(w_n^{2k}w_n^n) \\ &= A_1(w_n^{2k}) - w_n^kA_2(w_n^{2k}) \\ &=A_1(w_{\frac{n}{2}}^k) - w_n^kA_2(w_{\frac{n}{2}}^k) \end {aligned} A(wnk+2n)=A1((wnk+2n)2)+xA2((wnk+2n)2)=A1(wn2kwnn)+wnk+2nA2(wn2kwnn)=A1(wn2k)−wnkA2(wn2k)=A1(w2nk)−wnkA2(w2nk)
可以看到对于 k=n2k = \frac{n}{2}k=2n 的中介线来说,A(wnk)A(w_n^k)A(wnk) 和 A(wnk+n2)A(w_n^{k+\frac{n}{2}})A(wnk+2n) 都可以通过 wn2kw_{\frac{n}{2}}^kw2nk 进行计算
这样时间复杂度就降为了 O(nlog2n)O(nlog_2n)O(nlog2n)
蝴蝶变换 Cooley-Turkey
刚提到对于当前层确定的位置 iii,可以通过下一层的两个值对当前值进行更新
开始肯定想着用递归的方式进行操作,但是有更为便捷的二进制反转方法
- 以下 kkk 均为 aka_kak 中的 kkk
kkk | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
二进制 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
一次变换之后,将偶数下标放在一起、奇数下标放在一起,重新变化成以下数列(前4个为一组,后4个为一组)
kkk | 0 | 2 | 4 | 6 | 1 | 3 | 5 | 7 |
---|
二次变换之后,将两组的奇次项、偶次项再分开,变成以下数列(2、2、2、2分组)
kkk | 0 | 4 | 2 | 6 | 1 | 5 | 3 | 7 |
---|
三次变换之后,已经变成单独的一个一个的了,再观察他们的二进制,和原始序列k作比较
原始 kkk | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
二进制 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
kkk | 0 | 4 | 2 | 6 | 1 | 5 | 3 | 7 |
二进制 | 000 | 100 | 010 | 110 | 001 | 101 | 011 | 111 |
这样的对比可以很容易看出,对于原始序列和变换之后的序列来说,他们就是对二进制做了一个反转操作,即 1 (001) 变成了 4 (100)
那如果我们在最开始的时候,就将序列做了二进制反转操作,就可以从前往后依次顺序运算,而不需要使用递归的方式
以刚刚的序列为例子
反转后的 kkk | 0 | 4 | 2 | 6 | 1 | 5 | 3 | 7 |
---|---|---|---|---|---|---|---|---|
计算内容 | A(w10)=a0w10A(w_1^0) = a_0w_1^0A(w10)=a0w10 | A(w14)A(w_1^4)A(w14) | A(w12)A(w_1^2)A(w12) | A(w16)A(w_1^6)A(w16) | A(w11)A(w_1^1)A(w11) | A(w15)A(w_1^5)A(w15) | A(w13)A(w_1^3)A(w13) | A(w17)=a7w17A(w_1^7) = a_7w_1^7A(w17)=a7w17 |
第一次合并
kkk | 0 | 4 | 2 | 6 | 1 | 5 | 3 | 7 |
---|---|---|---|---|---|---|---|---|
计算内容 | A(w20)=A1(w10)+w20A2(w14)A(w_2^0) = A_1(w_1^0) + w_2^0A_2(w_1^4)A(w20)=A1(w10)+w20A2(w14) | A(w24)=A1(w10)−w20A2(w14)A(w_2^4) = A_1(w_1^0) - w_2^0A_2(w_1^4)A(w24)=A1(w10)−w20A2(w14) | A(w22)A(w_2^2)A(w22) | A(w26)A(w_2^6)A(w26) | A(w21)A(w_2^1)A(w21) | A(w25)A(w_2^5)A(w25) | A(w23)A(w_2^3)A(w23) | A(w27)A(w_2^7)A(w27) |
这里的 A1(w10)A_1(w_1^0)A1(w10) 就对应了第一个表中的 A(w10)A(w_1^0)A(w10)
且 k=4k = 4k=4 的时候取值为 w20w_2^0w20 是因为在 k>n2k > \frac{n}{2}k>2n 的时候,xxx 取的是 wnk+n2w_n^{k + \frac{n}{2}}wnk+2n,所以 kkk 也要相应的减去 n2\frac{n}{2}2n
第二次合并
kkk | 0 | 2 | 4 | 6 | 1 | 3 | 5 | 7 |
---|---|---|---|---|---|---|---|---|
计算内容 | A(w40)=A1(w20)+w40A2(w24)A(w_4^0) = A_1(w_2^0) + w_4^0A_2(w_2^4)A(w40)=A1(w20)+w40A2(w24) | A(w42)=A1(w20)−w40A2(w24)A(w_4^2) = A_1(w_2^0) - w_4^0A_2(w_2^4)A(w42)=A1(w20)−w40A2(w24) | A(w44)A(w_4^4)A(w44) | A(w46)A(w_4^6)A(w46) | A(w41)A(w_4^1)A(w41) | A(w43)A(w_4^3)A(w43) | A(w45)A(w_4^5)A(w45) | A(w47)A(w_4^7)A(w47) |
这里的 A1(w20)A_1(w_2^0)A1(w20) 就对应了第二个表中的 A(w20)A(w_2^0)A(w20)
第三次合并
kkk | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
计算内容 | A(w80)=A1(w40)+w80A2(w42)A(w_8^0) = A_1(w_4^0) + w_8^0A_2(w_4^2)A(w80)=A1(w40)+w80A2(w42) | A(w81)=A1(w40)−w80A2(w42)A(w_8^1) = A_1(w_4^0) - w_8^0A_2(w_4^2)A(w81)=A1(w40)−w80A2(w42) | A(w82)A(w_8^2)A(w82) | A(w83)A(w_8^3)A(w83) | A(w84)A(w_8^4)A(w84) | A(w85)A(w_8^5)A(w85) | A(w86)A(w_8^6)A(w86) | A(w87)A(w_8^7)A(w87) |
所以在最后一次合并之后就得到了所有的 A(x)A(x)A(x)
成功的从系数表示法转换成点值表示法!
逆快速傅里叶变换(IFFT)
当然我们从系数表示法转换成点值表示法只是为了计算卷积的时候减小时间复杂度,但最后对我们有帮助、便于分析的仍然是系数表示法
所以在对点值表示法的多项式进行卷积之后,仍需要将其再次转换回系数表示法
这种转换方式称为逆快速傅里叶变换
那等于说我们给出了 nnn 个线性方程组,然后需要对其进行求解
a0(wn0)0+a1(wn0)1+......+an−1(wn0)n−1=A(wn0)a0(wn1)0+a1(wn1)1+......+an−1(wn1)n−1=A(wn1)......a0(wnn−1)0+a1(wnn−1)1+......+an−1(wnn−1)n−1=A(wnn−1)\begin{aligned} a_0(w_n^0)^0 + a_1(w_n^0)^1 + ...... + a_{n-1}(w_n^0)^{n-1} &= A(w_n^0) \\ a_0(w_n^1)^0 + a_1(w_n^1)^1 + ...... + a_{n-1}(w_n^1)^{n-1} &= A(w_n^1) \\ ......\\ a_0(w_n^{n-1})^0 + a_1(w_n^{n-1})^1 + ...... + a_{n-1}(w_n^{n-1})^{n-1} &= A(w_n^{n-1}) \\ \end{aligned} a0(wn0)0+a1(wn0)1+......+an−1(wn0)n−1a0(wn1)0+a1(wn1)1+......+an−1(wn1)n−1......a0(wnn−1)0+a1(wnn−1)1+......+an−1(wnn−1)n−1=A(wn0)=A(wn1)=A(wnn−1)
将其写成矩阵的形式有
[(wn0)0(wn0)1...(wn0)n−1(wn1)0(wn1)1...(wn0)n−1......(wnn−1)0(wnn−1)1...(wnn−1)n−1][a0a1...an−1]=[A(wn0)A(wn1)...A(wnn−1)]\left[ \begin{matrix} (w_n^0)^0 & (w_n^0)^1 & ... & (w_n^0)^{n-1} \\ (w_n^1)^0 & (w_n^1)^1 & ... & (w_n^0)^{n-1} \\ ...... \\ (w_n^{n-1})^0 & (w_n^{n-1})^1 & ... & (w_n^{n-1})^{n-1} \end{matrix} \right] \left[ \begin{matrix} a_0 & \\ a_1 & \\ ...\\ a_{n-1} & \end{matrix} \right] = \left[ \begin{matrix} A(w_n^0) \\ A(w_n^1) \\ ...\\ A(w_n^{n-1}) \end{matrix} \right] ⎣⎢⎢⎡(wn0)0(wn1)0......(wnn−1)0(wn0)1(wn1)1(wnn−1)1.........(wn0)n−1(wn0)n−1(wnn−1)n−1⎦⎥⎥⎤⎣⎢⎢⎡a0a1...an−1⎦⎥⎥⎤=⎣⎢⎢⎡A(wn0)A(wn1)...A(wnn−1)⎦⎥⎥⎤
定义第一个矩阵为D、第二个矩阵为V、第三个矩阵为E
按照矩阵乘法,有
eij=Σk=0n−1dikvkj=Σk=0n−1wn−ikwnkj=Σk=0n−1wnk(j−i)\begin{aligned} e_{ij} & = \Sigma_{k=0}^{n-1}d_{ik}v_{kj} \\ &= \Sigma_{k=0}^{n-1}w_n^{-ik}w_n^{kj} \\ &=\Sigma_{k=0}^{n-1}w_n^{k(j-i)} \end{aligned} eij=Σk=0n−1dikvkj=Σk=0n−1wn−ikwnkj=Σk=0n−1wnk(j−i)
所以有
eij={ni=j0i≠je_{ij} = \begin{cases} & n & & i = j \\ & 0 & & i ≠ j \\ \end{cases} eij={n0i=ji̸=j
i≠ji≠ji̸=j 的时候可以根据等比序列求和公式得到和为0
由此可知,In=1nEI_n = \frac{1}{n}EIn=n1E,InI_nIn是一个 n×n 的单位矩阵
所以有 1nD=V−1\frac{1}{n}D = V^{-1}n1D=V−1,∵ EEE 和单位矩阵扯上联系了嘛
那么其实IFFT就是一个变换了一点点的FFT
如果说FFT用公式来表示是
X(k)=Σn=0N−1x(n)wNknX(k) = \Sigma_{n=0}^{N-1}x(n)w_N^{kn} X(k)=Σn=0N−1x(n)wNkn则IFFT用公式来表示就是
x(n)=1NΣn=0N−1X(k)wn−knx(n) = \frac{1}{N}\Sigma_{n=0}^{N-1}X(k)w_n^{-kn} x(n)=N1Σn=0N−1X(k)wn−kn
单位根取个负然后乘个 1N\frac{1}{N}N1
那总结一下FFT和IFFT的作用就是减少卷积运算的时间复杂度www
其他
- 其实是为了学习NTT
- 然而NTT还没看懂
- 先总结出一份FFT和IFFT的来
- NTT的尽快出吧QuQ
快速傅里叶变换(FFT)和逆快速傅里叶变换(IFFT)相关推荐
- [模板] 快速傅里叶变换(FFT)
快速傅里叶变换FFT 多项式 转换 快速傅里叶变换 铺垫 定理 算法构建 IFFT 递归版FFT&IFFT 迭代版FFT&IFFT 蝴蝶效应 Code 后记 多项式 假设有nnn次多项 ...
- Java中实现快速傅里叶变换FFT
Java中实现快速傅里叶变换FFT 一.概述 1.傅里叶变换(FT) 2.离散傅里叶变换(DFT) 3.快速傅里叶变换(FFT) 1)单位根 2)快速傅里叶变换的思想 3)蝶形图 4)快速傅里叶变换的 ...
- MATLAB 离散傅里叶变换(DFT)、逆离散傅里叶变换(IDFT)、快速傅里叶变换(FFT)的实现
离散傅里叶变换(DFT).逆离散傅里叶变换(IDFT)的实现 代码如下,其中xn为时序序列 clc;clear; xn=[7,6,5,4,3,2]; Xk=dft(xn,6); x=idft(Xk,6 ...
- 基于python的快速傅里叶变换FFT(一)
基于python的快速傅里叶变换FFT(一) FFT可以将一个信号变换到频域.有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了.这就是很多信号分析采用FFT变换的原因. ...
- 11.频域里的卷积——介绍,傅里叶变换和卷积,快速傅里叶变换(FFT)_1
目录 介绍 傅里叶变换和卷积 FFT 介绍 我们将继续讨论频率分析以及如何用频率分量的概念来研究图像.如果你还记得上次我们讲过的基于频率的图像分解的概念.我们通过给你们看这张照片来回忆它(如图).这是 ...
- MIT 线性代数 Linear Algebra 26:复矩阵,傅里叶矩阵, 快速傅里叶变换 FFT
这一讲我们来讲一下复矩阵.线性代数中,复矩阵是避免不了的话题,因为一个简单实矩阵都有可能有复数特征值. 复矩阵 我们着重看一下复矩阵和实矩阵在运算上的区别. 距离 首先,一个复数向量的的距离求法发生了 ...
- OpenCV快速傅里叶变换(FFT)用于图像和视讯流的模糊检测
OpenCV快速傅里叶变换(FFT)用于图像和视频流的模糊检测 翻译自[OpenCV Fast Fourier Transform (FFT) for blur detection in images ...
- 离散傅里叶变换 (DFT)、快速傅里叶变换 (FFT)
目录 离散傅里叶变换 (DFT) 离散傅里叶变换的基 离散傅里叶变换 快速傅里叶变换 (FFT) 卷积 线性时不变系统 傅里叶级数 参考文献 离散傅里叶变换 (DFT) 离散傅里叶变换的基 对于周期为 ...
- 傅里叶变换、离散傅里叶变换(DFT)、快速傅里叶变换(FFT)详解
前置知识 以下内容参考<复变函数与积分变换>,如果对积分变换有所了解,完全可以跳过忽略 复数的三角表达式如下 Z=r(cosθ+isinθ)Z=r(cos\theta+isin\theta ...
最新文章
- APPIUM Android 定位方式
- 如何生成表_SPSS简单操作 | 如何生成交叉表?
- 用python画四叶草代码-python turtle工具绘制四叶草的实例分享
- Json解析异常处理方式(JSONException: Value of type java.lang.String cannot be converted to JSONObject)...
- es获取最大时间的记录_大屏幕大智慧,腕上私教+生理周期,荣耀手表ES评测
- 三类医械计算机系统要求,三类医疗器械计算机管理系统要求
- redis集群搭建报错-(error) CLUSTERDOWN The cluster is down
- [css] 请说说在什么时候用transition?什么时候使用animation?
- 微信能远程控制电脑吗_神器分享:用微信就能远程控制电脑,这款神器有些厉害...
- 安卓案例:标签页演示
- Python集合常用函数使用详解(内附详细案例)
- aws平台中为ec2实例添加双网卡
- 转:git设置过滤忽略的文件或文件夹
- java类的封装关系_Java—类的封装、继承与多态
- 复旦和同济计算机学硕,考研择校:复旦、同济、上财哪个更有前途?看网友怎么说!...
- html+css 制作小米商城主体内容的商品展示
- ERP系统模块完全解析──主生产计划MPS
- 马云:30年后每对年轻人要养8个老人 管理5套房子
- 大学生开学需要准备哪些数码产品、五款大学生必买的电子产品
- 模数转换,你必须知道的8个经典ADC转换电路方案