C語言實現FFT

C語言實現FFT

參考:
https://blog.csdn.net/YAOHAIPI/article/details/102307425
https://www.cnblogs.com/wuyepeng/p/9795479.html
https://www.cnblogs.com/enzymii/p/8426709.html
http://blog.miskcoo.com/2015/04/polynomial-multiplication-and-fast-fourier-transform
FFT中的位反轉算法:
https://www.cnblogs.com/jackmaxwell/p/7931494.html

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define N 1024

int size=0;   //定義數據長度
double PI=4.0*atan(1); //定義π 因爲tan(π/4)=1 所以arctan(1)*4=π,增加π的精度

typedef struct  //定義一個結構體表示覆數的類型
{       
	double real;
	double imag;
}complex;
complex x[N], *W;   //定義輸入序列和旋轉因子

//定義複數加減乘法
void add(complex a,complex b,complex *c) //複數加法,結果放入c中
{
	c->real=a.real+b.real;
	c->imag=a.imag+b.imag;
}
void sub(complex a,complex b,complex *c)  //複數減法,結果放入c中
{
	c->real=a.real-b.real;
	c->imag=a.imag-b.imag;
}
void mul(complex a,complex b,complex *c)  //複數乘法,結果放入c中
{
	c->real=a.real*b.real - a.imag*b.imag;
	c->imag=a.real*b.imag + a.imag*b.real;
}


void output()   //輸出
{
	int i;
	for(i=0;i<size;i++)
	{	
		printf("%.4f",x[i].real);
		if(x[i].imag>=0.0001)         printf("+%.4fj\n",x[i].imag);
		else if(fabs(x[i].imag)<0.0001)      printf("\n");
		else       printf("%.4fj\n",x[i].imag);
	}
}


void change()  //位反轉運算
{
	complex temp;
	unsigned short i=0,j=0,k=0;
	double t;
	for(i=0;i<size;i++)
	{
		k=i;
		j=0;
		t=(log(size)/log(2));  //算出序列的級數log2N,利用換底公式
		while( (t--)>0 )  //利用按位與以及循環實現碼位顛倒
		{
			j=j<<1;
			j=j|(k & 1);
			k=k>>1;
		}
		if(j>i)   //將x(n)的碼位互換
		{
			temp=x[i];
			x[i]=x[j];
			x[j]=temp;
		}
	}
	output();
}
void transform()   //旋轉因子wn
{
	int i;
	W=(complex *)malloc(sizeof(complex) * size);
	for(i=0;i<size;i++)
	{
		W[i].real=cos(2*PI/size*i);
		W[i].imag=-1*sin(2*PI/size*i);
	}
}

void fft()  //蝶形運算
{
	int i=0,j=0,k=0,m=0;
	complex q,y,z;
	change();
	for(i=0;i<log(size)/log(2) ;i++)   //蝶形運算的級數
	{
		m=1<<i;     //兩個輸入點的距離,相當於m=2^i,蝶形運算倆輸入間距=2^(L-1)  L表示級數
		for(j=0;j<size;j+=2*m)   //一組一組遍歷蝶形運算   以3級蝶形運算爲例,三級分別有4組,2組,1組
		{
			for(k=0;k<m;k++)   //每個組內的蝶形運算
			{
				mul(x[k+j+m],W[size*k/2/m],&q);   //x[k+j+m]*Wn
				add(x[j+k],q,&y);            //x[j+k]+x[k+j+m]*Wn
				sub(x[j+k],q,&z);            //x[j+k]-x[k+j+m]*Wn
				x[j+k]=y;      //迭代到下一級
				x[j+k+m]=z;    //迭代到下一級
			}
		}
	}
}
int main()
{
	int i;
	printf("輸入數據個數\n");
	scanf("%d",&size);//輸入數據的長度(2的整數次冪)
	printf("輸入數據的實部、虛部\n");
	for(i=0;i<size;i++)
	{
		scanf("%lf%lf",&x[i].real,&x[i].imag);  //輸入複數的實部和虛部
	}
	printf("輸出倒序後的序列\n");
	transform();//變換序列順序
	fft();//蝶形運算
	printf("輸出FFT後的結果\n");
	output();//輸出結果
    getchar();getchar();
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章