一、什么是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 ( n 2 ) O(n^2) O(n2)的。难道大整数乘法就只能是 O ( n 2 ) O(n^2) O(n2)吗?不甘心的同学可以发现,大整数乘法复杂度的瓶颈可能在“多项式转换成点值表示”这一步做改进,只要完成这一步就可以O(n)的复杂度求答案了。傅里叶变换的发明就是为完成这个使命。
三、FFT过程分析
1. 复数的引入
傅里叶规定点值表示中的n个x为n个模长为1的复数。
而这n个复数不是随机寻找的,而是把单位圆(圆心为原点、1为半径的圆)n等分,取这n个点所表示的复数,即分别以这n个点的横坐标为实部、纵坐标为虚部,所构成的复数。
从点(1,0)开始,逆时针将这n个点从0开始编号,第k个点对应的虚数记作 w n k w^k_n wnk,根据复数相乘时模长相乘幅角相加可以看出, w n k w^k_n wnk是 w n 1 w^1_n wn1的k次方,所以 w n 1 w^1_n wn1被称为n次单位根。
根据每个复数的幅角,可以计算出所对应的点。 w n k w^k_n wnk对应的点是 ( c o s 2 π k n , s i n 2 π k n ) (cos2π \frac{k}{n},sin2π\frac{k}{n}) (cos2πnk,sin2πnk),也就是说这个复数是 c o s 2 π k n + i s i n 2 π k n cos2π\frac{k}{n}+isin2π\frac{k}{n} cos2πnk+isin2πnk。
把这n个复数 ω n 0 , ω n 1 , ω n 2 , . . . , ω n n − 1 ω^0_n,ω^1_n,ω^2_n,...,ω^{n-1}_n ωn0,ωn1,ωn2,...,ωnn−1代入多项式,能得到一种特殊的点值表示,这种点值表示就叫离散傅里叶变换
2. 分治的思想
我们要计算n个采样点
p = p 0 , p 1 , . . . , p n − 1 p={p_0,p_1,...,p_{n-1}} p=p0,p1,...,pn−1
的傅里叶变换,可以归结为计算多项式
f ( x ) = p 0 + p 1 x + p 2 x + . . . + p n − 1 x n − 1 f(x)=p_0+p_1x+p_2x+...+p_{n-1}x^n-1 f(x)=p0+p1x+p2x+.