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;
}