快速傅里叶变换FFT总结

来源:互联网 发布:dnf战斗力查询 软件 编辑:程序博客网 时间:2024/06/05 05:08

快速傅里叶变换,在竞赛中离散傅里叶变换DFT及其逆变换IDFT尤为常用,主要用于快速求多项式的乘积。形式化地说,多项式就是某个f(x)=i=0naixi,两个系数分别为aibi,那么(f×g)(x)=f(x)g(x)=i=0nj=0naibjxi+j,容易看出这个多项式是2n次的。
【补充知识1】我们接着先看一下一个叫卷积的东西。卷积实际上就是对应相乘,(fg)(x)=i=0naibixi,可以稍微理解一下,实质上我们如果将乘法视为一种变换,卷积就是在向量上的变换的叠加。
【补充知识2】
其实,对于一条n次的多项式曲线,我们可以通过类比认识到我们需要n+1个不同的点就可以唯一确定这条曲线。比如说一次函数需两个点,二次函数需三个点,等等。我们考虑到,我们表达这些函数为f(x)=i=0naixi,那么如果我们现在得知了n+1个函数上的点,直接代入就可以相应得出n+1个方程,由于点两两不同,所以这个方程组一定恰有一组解,这也就确定了一条唯一的曲线。

好的,接下来是真正的内容。
我们可以发现,要确定最终的(fg)(x),需要使用2n+1个点值表达,也就是在最终结果曲线上的2n+1个点。我们如果考虑在f(x)g(x)上取2n+1个点,设为(xi,yfi)(xi,ygi),我们发现只要将其卷积一下,我们就能够找到这2n+1个点。这是很好理解的,因为将yfiygi卷积后作为新的纵坐标所得到的点,显然就在(fg)(x)上。
那么我们的问题就只剩下怎样计算和如何再次快速确定了。
我们考虑下分治,如果我们将系数向量中奇数项和偶数项分开来,我们会发现所得的两个式子间有一定的相似性:

a1x1+a3x3++a2k+1x2k+1
a0x0+a2x2++a2kx2k+

实际上,我们考虑将上面的式子变为x(a1x0+a3x2++a2k+1x2k+),再将各项的次数折半(因为是偶数),我们现在就能够得到两个规模相对于原来的问题减半的子问题,可以递归求解,这里我们就得出了DFT的算法,由主定理对于T(n)=2T(n2)+O(n),马上看出其复杂度O(nlgn)
但是,在还原的时候,我们却遇到了一个困难:我们如何将点值表达快速变为系数表达?难道我们去用高斯消元法?这样O(n3)岂不是比原来还慢?我们来观察一下DFT的实质。我们将DFT的效果写成这样一个矩阵:
111x0x1xnxn0xn1xnn

稍微解释下,根据线性代数,这个东西乘上我们的系数向量之后所得就是对应的x=x0,1,,n(fg)(x)的结果。这个东西是很显然的,考虑用线性变换的角度理解。
然后我们考虑DFT的逆变换,即所谓IDFT,其的实质就是乘上DFT所乘上的这个矩阵的一个逆矩阵。由逆矩阵定义,我们可以考虑猜想在逆矩阵中(j,k)处,数为xjk×C,其中C是一个常数。那么如果将两个矩阵乘起来,再考虑(j,j)处的值,为
k=0nxjjkC
要满足逆矩阵条件VV1=In,我们需要当且仅当j=j的时候上式为1,其余情况为0。先看第一个条件,代进去得到nk=0C=1,得C=1n。代回去并根据第二个条件我们有
k=0nxjjk=0(jj)

然后我并不知道怎么一直推下去,于是我们直接来一个构造法。我们令xk=wkn,然后我们就得到了一个等比数列,按照上式求和根据公式可以得到
k=0n(wkn)jj=k=0n(wjjn)k=(wjjn)n1wjjn1=0
,即(这里跳了一步移项)
(wjjn)n=1
我们又考虑到,jj取遍0n间的所有值,所以上式可以改为(wkn)n=wknn=1,其中k的值域为从nn
然后,我们考虑先取k=1,本质上这里说的就是我们需要这样的一类不同的2n个数使得(wn)n=1。显然在实数域中只能有1(以及1,因为我们在分治的时候预先补了零使得次数是2d)满足这个性质,显然太少了,怎么办?
我们考虑扩展取值范围。一种方法,就是不只考虑实轴,我们可以考虑下复平面。也就是说,我们可以不只考虑aR,而是考虑所有a+biC,其中a,bR,而这里的i,是一个曾经数学中往往避开的事物,满足i2=1。实质上来说,复数可以理解为一种向量,比如说两个复数相加就是向量作用的叠加,而两个复数的积,则是另一种程度上的叠加。比方说我们考虑到,我们用极坐标也可以确定向量,进而确定复数,我们由变换
f(x)={xy==ρcosθρsinθ

我们可以得出在极坐标意义下a+bi可以写成ρ(cosθ+isinθ),考虑两个复数相乘的时候,我们有(涉及高中三角学知识,若无基础可以跳过)
ρ1(cosθ1+isinθ1)×ρ2(cosθ2+isinθ2)=ρ1ρ2(cosθ1cosθ2+isinθ1cosθ2+isinθ2cosθ1sinθ1sinθ2)
考虑利用各种和差化积公式(具体推导这里略去),得到乘积为ρ1ρ2(cos(θ1+θ2)+isin(θ1+θ2)),实质上就是长度相乘,旋转角相加。
我在继续来考量下这个概念有什么用。上面的(wn)n=1在变换群里面其实对应的是一种循环,称作生成元。我们考虑到,如果对应在复平面上,我们考虑令ρ=1,然后长度上不管怎么乘都不会变,最后也就是1(由于ρ被要求是非负实数),然后神奇的东西来了,我们令θ=2π/n,也就是将整个复平面划分成n份,那么根据我们刚才的相乘原则,这个复数向量cos(2πn+isin(2πn))实际上就是我们所要求的wn。继续考量下它的性质,如果考虑wkn(0k<n),其的n次方也是1,因为(wkn)n=(wnn)k=1k=1,同时在复数意义下,这n个数也是两两不同的,所以我们如果代入这n个数,我们就可以在O(nlgn)的时间内计算出IDFT,而且代码上和DFT差不多,因为只是最后多除了个n,同时把wkn换成了wkn,因此也可以写在一起,传入参数在某几步上加个特判。
同时复数还有性质wk+n/2n=wkn×wn/2n,而又容易由角度看出wn/2n=1,所以wk+n/2n=wkn。这个东西可以用来稍微改进下DFT,这样我们的计算量大概减少了一半左右,代码也是更容易写了。
不过,虽然说DFT在理论上是没有误差的,但是鉴于三角函数浮点数上计算有不小的误差,所以说如果多项式的系数向量都是整数的话,显然最后的系数向量也是整数,那么我们完全可以不在复数域下进行,而是在另一种同样具有群性质的数系下进行,比如说我们同样熟悉的模域下。而这就要在数论上进行讨论了,所以并不写,坑等以后再填……
好吧,最后再提一下,其实是有四种傅里叶变换的,分别对应着时域和频域上的离散和连续,其中如果两个域都是连续的,实质上就是傅里叶级数,也就是将一个函数展开成许多三角函数构成的无穷级数。再换句话说,就是用许多正(余)弦波的叠加去不断拟合某条给定的曲线。当然,你也可以用方波去拟合,这就涉及到快速沃尔什变换(FWT)了。

原创粉丝点击