串行FFT递归算法(蝶式递归计算原理)求傅里叶变换摘要FFT,即为快速傅氏变换,是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。
它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。
设x(n)为N项的复数序列,由DFT变换,任一X(m)的计算都需要N次复数乘法和N-1次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法,即使把一次复数乘法和一次复数加法定义成一次“运算”(四次实数乘法和四次实数加法),那么求出N项复数序列的X(m),即N点DFT变换大约就需要N^2次运算。
当N=1024点甚至更多的时候,需要N2=1048576次运算,在FFT中,利用WN的周期性和对称性,把一个N项序列(设N=2k,k为正整数),分为两个N/2项的子序列,每个N/2点DFT变换需要(N/2)^2次运算,再用N次运算把两个N/2点的DFT变换组合成一个N点的DFT变换。
这样变换以后,总的运算次数就变成N+2(N/2)^2=N+N^2/2。
继续上面的例子,N=1024时,总的运算次数就变成了525312次,节省了大约50%的运算量。
而如果我们将这种“一分为二”的思想不断进行下去,直到分成两两一组的DFT运算单元,那么N点的DFT变换就只需要Nlog(2)(N)次的运算,N在1024点时,运算量仅有10240次,是先前的直接算法的1%,点数越多,运算量的节约就越大,这就是FFT的优越性。
关键字:FFT 蝶式计算傅里叶变换目录一.题目及要求 (1)1.1题目 (1)二.设计算法、算法原理 (1)2.1算法原理与设计 (1)2.2设计步骤 (2)三.算法描述、设计流程 (4)3.1算法描述 (4)3.2流程图 (6)四.源程序代码及运行结果 (8)4.1源程序代码 (8)4.2运行结果 (13)五.算法分析、优缺点 (15)5.1算法分析 (15)5.2优缺点 (16)六.总结 (17)七.参考文献 (18)一.题目及要求1.1题目对给定的)23,27,16,8,30,74,22,21(--=α,利用串行FFT 递归算法(蝶式递归计算原理)计算其傅里叶变换的结果。
1.2要求利用串行递归与蝶式递归原理,对给定的向量求解傅里叶变换的结果。
二.设计算法、算法原理2.1算法原理与设计蝶式递归计算原理:令 为n/2次单位元根,则有 , 将b 向量的偶数项 和奇数项 分别记为 和 。
注意推导中反复使用: 。
图2.1 公式图形)2//(2~n i e πω=2~ωω=Tn b b b ),...,,(220-Tn b b b ),...,,(131-Tnb b b ),...,,(1102-'''T nb b b ),...,,(1102-''''''ppsn n nωωωωω==-==+,1,1,1ln2/2.2设计步骤DFT a a a a a a b b b T n T n n n n 的是因此,向量),...,,(),...,,(11110220222--+-+++DFT a a a a a a b b b T n Tn n n n n 的是因此,向量))(),...,(),((),...,,(1111101312222---+----ωω()()()()1,,1,0)(~)(~)(~)(~)()()()()(21011122211011122241120112241211224120122222222222222222222-=+=++++++++=++++++++=+++++++++==='∑∑-=+---++---++--++---=n k kk l k n l l l n ll l n lll llln k klk l l l a a a aa a a a a a a a a a a a a a a a a a a a a a ab b nn nn n n n n n n n n n n n n n n ωωωωωωωωωωωωωω偶数时:()()()()()()()1,,1,0)(~)(~)(~)(~)()()()()(21011112222110111122224112011121211122241201)12(11)12(1)12(1)12(12)12(211201)12(12222222222222222222222222222-=-=-++-+-+-=-++-+-+-=----++++=++++++++===''∑∑-=+----++----++---+----+-++++-+-++-=++n k kk k l k n l l l n llln llllln l n l l l l l n k k k l l l l a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a b b n n n n n n n n n n n n n n n n n n n n n n n n nn n ωωωωωωωωωωωωωωωωωωωωωωωωωωωωωωω奇数时:对于以上的分析可画出如图 2.2所示的离散傅里叶变换递归计算流图。
图2.3就是一个按此递归方法计算的n=8的FFT 蝶式计算图。
FFT 的蝶式递归计算图(有计算原理推出):图2.2 递归计算流图特别的,n=8的FFT 蝶式计算图(展开的):...a 0a1a n -1DFT(n /2)DFT(n /2).........+++---1-a (a )ωn 2-1n 2-1n-1-a (a )ωn 2+11-a a n20+a a n 2-1n-1+a a 20+a a n 2+11a n 2-1a n 2an 2+1......ωn 2-1ω图2.3 蝶式计算图按输入元素k a 展开,前面将输出序列之元素j b 按其偶下标(l j 2=)和(12+=l j )展开,导出∑-=++1022)(~n n k k k lk a a ω和∑-=+-1022)(~nn k kk k l k a a ωω递归计算式,按此构造出了如图1所示的FFT 递归计算流程图。
事实上,我们也可以将输入序列之元素k a 按其偶下标(k 2) 和几下标(12+k )展开,则导出另一种形式的FFT 递归计算式 ∑-==10n k k kj j a w b 。
三.算法描述、设计流程3.1算法描述SISD 上的FFT 分治递归算法:输入: a=(a 0,a 1,…,a n-1); 输出: B=(b 0,b 1,…,b n-1) Procedure RFFT(a,b) beginif n=1 then b 0=a 0 else(1)RFFT(a 0,a 2,…,a n-2, u 0,u 1,…,u n/2-1) (2)RFFT(a 1,a 3,…,a n-1, v 0,v 1,…,v n/2-1) (3)z=1(4)for j=0 to n-1 do(4.1)b j =u j mod n/2+zv j mod n/2 (4.2)z=z ωendfor endif end注: (1)算法时间复杂度t(n)=2t(n/2)+O(n)t(n)=O(nlogn)n=8的FFT蝶式计算图:图3.1 FFT蝶式计算图n=6的FFT递归计算流程图:图3.2 FFT递归计算流程图3.2流程图四.源程序代码及运行结果4.1源程序代码/************FFT***********/#include <stdio.h> //整个程序输入和输出利用同一个空间x[N],节约空间#include <math.h>#include <stdlib.h>#define N 1000 //定义输入或者输出空间的最大长度typedefstruct{double real;doubleimg;}complex; //定义复数型变量的结构体void fft(); //快速傅里叶变换函数声明void initW(); //计算W(0)~W(size_x-1)的值函数声明void change(); //码元位置倒置函数函数声明void add(complex,complex,complex *); /*复数加法*/void mul(complex,complex,complex *); /*复数乘法*/void sub(complex,complex,complex *); /*复数减法*/void divi(complex,complex,complex *); /*复数除法*/void output(); /*输出结果*/complex x[N],*W; /*输出序列的值*/intsize_x=0; /*输入序列的长度,只限2的N次方*/double PI; //pi的值int main(){inti;system("cls");PI=atan(1)*4;printf("Please input the size of x:\n"); /*输入序列的长度*/scanf("%d",&size_x);printf("Please input the data in x[N]:(such as:5 6)\n");for(i=0;i<size_x;i++) /*输入序列对应的值*/ scanf("%lf %lf",&x[i].real,&x[i].img);initW(); //计算W(0)~W(size_x-1)的值fft(); //利用fft快速算法进行DFT变化output(); //顺序输出size_x个fft的结果return 0;}/*进行基-2 FFT运算,蝶形算法。
这个算法的思路就是,先把计算过程分为log(size_x)/log(2)-1级(用i控制级数);然后把每一级蝶形单元分组(用j控制组的第一个元素起始下标);最后算出某一级某一组每一个蝶形单元(用k控制个数,共l个)。
*/voidfft(){inti=0,j=0,k=0,l=0;complexup,down,product;change(); //实现对码位的倒置for(i=0;i<log(size_x)/log(2);i++) //循环算出fft的结果{l=1<<i;for(j=0;j<size_x;j+=2*l){for(k=0;k<l;k++) //算出第i级内j组蝶形单元的结果{ //算出j组中第k个蝶形单元mul(x[j+k+l],W[(size_x/2/l)*k],&product); /*size/2/l是该级W的相邻上标差,l是该级该组取的W总个数*/add(x[j+k],product,&up);sub(x[j+k],product,&down);x[j+k]=up; //up为蝶形单元右上方的值x[j+k+l]=down; //down为蝶形单元右下方的值}}}}void initW() //计算W的实现函数{inti;W=(complex *)malloc(sizeof(complex) * size_x);/*申请size_x个复数W的空间(这部申请的空间有点多,实际上只要申请size_x/2个即可)*/for(i=0;i<(size_x/2);i++)/*预先计算出size_x/2个W的值,存放,由于蝶形算法只需要前size_x/2个值即可*/ {W[i].real=cos(2*PI/size_x*i); //计算W的实部W[i].img=-1*sin(2*PI/size_x*i); //计算W的虚部}}void change() //输入的码组码位倒置实现函数{complex temp;unsigned short i=0,j=0,k=0;double t;for(i=0;i<size_x;i++){k=i;j=0;t=(log(size_x)/log(2));while((t--)>0){j=j<<1;j|=(k & 1);k=k>>1;}if(j>i){temp=x[i];x[i]=x[j];x[j]=temp;}}}void output() //输出结果实现函数{inti;printf("The result are as follows\n");for(i=0;i<size_x;i++){printf("%.4f",x[i].real); //输出实部if(x[i].img>=0.0001) //如果虚部的值大于0.0001,输出+jx.img的形式printf("+j%.4f\n",x[i].img);else if(fabs(x[i].img)<0.0001)printf("\n");elseprintf("-j%.4f\n",fabs(x[i].img));//如果虚部的值小于-0.0001,输出-jx.img的形式}}void add(complex a,complexb,complex *c) //复数加法实现函数{c->real = a.real + b.real; //复数实部相加c->img = a.img + b.img; //复数虚部相加}void mul(complex a,complexb,complex *c) //复数乘法实现函数{c->real = a.real*b.real - a.img*b.img; //获取相乘结果的实部c->img = a.real*b.img + a.img*b.real; //获取相乘结果的虚部}void sub(complex a,complexb,complex *c) //复数减法实现函数{c->real = a.real - b.real; //复数实部相减c->img = a.img - b.img; //复数虚部相减}void divi(complex a,complexb,complex *c) //复数除法实现函数{c->real = (a.real*b.real + a.img*b.img) / (b.real*b.real+b.img*b.img);//获取相除结果的实部c->img = (a.img*b.real - a.real*b.img) / (b.real*b.real+b.img*b.img);//获取相除结果的虚部}4.2运行结果(1)处理器p=8:α时串行FFT输出结果图4.1当)8,7,6,5,4,3,2,1(=(2)处理器p=8:α时输出结果与计算结果相符如图4.2所示当)(-,21-=,3023,22,27,16,8,74图4.2运行图五.算法分析、优缺点5.1算法分析(1)FFT算法的基本原理是把长序列的DFT逐次分解为较短序列的DFT。