一、什么是FFT?
DFT虽好,但是其计算的次数太多,不利于大数据量的计算,FFT是DFT的快速算法,可以节省大量的计算时间,快速傅里叶变换(FFT)是一种能在O(nlogn)的时间内将一个多项式转换成它的点值表示的算法。
-
点值表示法:
设一个函数f(x)为n-1次多项式,带入一个n个不同的x会得到n个不同的y,这n对(x,y)唯一确定了该多项式,即只有一个多项式能同时满足“代入这些x,得到的分别是这些y”。
二、FFT的目的
FFT可以用来加速多项式乘法。假设有两个n−1次多项式A(x)和B(x),我们的目标是——把它们乘起来。
普通的多项式乘法的复杂度是O(n2)的,我们要枚举A(x)中的每一项,分别与B(x)中的每一项相乘,来得到一个新的多项式C(x)。
但是,如果A(x),B(x)两个多项式用点值表示的方法进行相乘,复杂度是O(n)的。具体方法:C(xi)=A(xi)×B(xi),所以枚举xi即可。
要是我们把两个多项式转换成点值表示,再相乘,再把新的点值表示转换成多项式岂不就可以O(n)的复杂度来解决多项式乘法了!
显然,把多项式转换成点值表示的朴素算法是O(n2)O(n^2)O(n2)的。难道大整数乘法就只能是O(n2)O(n^2)O(n2)吗?不甘心的同学可以发现,大整数乘法复杂度的瓶颈可能在“多项式转换成点值表示”这一步做改进,只要完成这一步就可以O(n)的复杂度求答案了。傅里叶变换的发明就是为完成这个使命。
三、FFT过程分析
1. 复数的引入
傅里叶规定点值表示中的n个x为n个模长为1的复数。
而这n个复数不是随机寻找的,而是把单位圆(圆心为原点、1为半径的圆)n等分,取这n个点所表示的复数,即分别以这n个点的横坐标为实部、纵坐标为虚部,所构成的复数。
从点(1,0)开始,逆时针将这n个点从0开始编号,第k个点对应的虚数记作wnkw^k_nwnk,根据复数相乘时模长相乘幅角相加可以看出,wnkw^k_nwnk是wn1w^1_nwn1的k次方,所以wn1w^1_nwn1被称为n次单位根。
根据每个复数的幅角,可以计算出所对应的点。wnkw^k_nwnk对应的点是(cos2πkn,sin2πkn)(cos2π \frac{k}{n},sin2π\frac{k}{n})(cos2πnk,sin2πnk),也就是说这个复数是cos2πkn+isin2πkncos2π\frac{k}{n}+isin2π\frac{k}{n}cos2πnk+isin2πnk。
把这n个复数ωn0,ωn1,ωn2,...,ωnn−1ω^0_n,ω^1_n,ω^2_n,...,ω^{n-1}_nωn0,ωn1,ωn2,...,ωnn−1代入多项式,能得到一种特殊的点值表示,这种点值表示就叫离散傅里叶变换
2. 分治的思想
我们要计算n个采样点
p=p0,p1,...,pn−1p={p_0,p_1,...,p_{n-1}}p=p0,p1,...,pn−1
的傅里叶变换,可以归结为计算多项式
f(x)=p0+p1x+p2x+...+pn−1xn−1f(x)=p_0+p_1x+p_2x+...+p_{n-1}x^n-1f(x)=p0+p1x+p2x+...+p