DFT,IDFT,FFT,IFFT算法的C++实现

  • Post author:
  • Post category:其他

DFT,FFT的算法原理见:https://zh.wikipedia.org/wiki/%E5%BF%AB%E9%80%9F%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2

 

#include <iostream>
#include <complex>
#include <cmath>
#include <vector>
#define eps 1e-6 
#define PI 3.14159265354
typedef std::complex<double> complex_t;
using namespace std;
 
//旋转因子的计算 
complex_t W(int k,int n,int N){
	return complex_t(cos(2*PI*k*n/N),-sin(2*PI*k*n/N));
}
 
//格式化 零 
complex_t format(complex_t &c){
	if(fabs(c.real())<eps) c.real()=0;
	if(fabs(c.imag())<eps) c.imag()=0;
	return c;
}
 
double format(double &c){
	if(fabs(c)<eps) c=0;
	return c;
}
 
//离散序列的DFT计算,只针对实数序列 ,完全按照DFT的公式来计算,O(n^2)的复杂度
void DFT(vector<double> &x_n,vector<complex_t> &X_k){
	X_k.clear();
	int N=x_n.size();
	for(int k=0;k<N;++k){
		complex_t t(0,0);
		for(int n=0;n<N;++n){
			t+=x_n[n]*W(k,n,N);
		}
		X_k.push_back(format(t));
	}
	
	int cnt=0;
	for(int i=0;i<N;++i){
		if(cnt==(int)sqrt(N)){
			cout<<endl;
			cnt=0;
		}
		++cnt;
		cout<<format(X_k[i])<<" ";
	}
	cout<<endl;
	
}
 
//IDFT的计算,只针对实数序列  
void IDFT(vector<complex_t> &X_k,vector<double> &x_n){
	x_n.clear();
	int N=X_k.size();
	for(int n=0;n<N;++n){
		complex_t t(0,0);
		for(int k=0;k<N;++k){
			t+=X_k[k]*W(k,-n,N);
		}
		x_n.push_back(t.real()/N);//运算结果只剩下实部 
		//cout<<(t/(double)N)<<endl; 
	}
	int cnt=0;
	for(int i=0;i<N;++i){
		if(cnt==(int)sqrt(N)){
			cout<<endl;
			cnt=0;
		}
		++cnt;
		cout<<format(x_n[i])<<" ";
	}
	cout<<endl;
	
}
 
void DFT_test(){
	int N=64;
	vector<double> x_n(N);
	vector<complex_t> X_k(N);
	for(int i=0;i<N;++i){
		x_n[i]=i;
	}
	DFT(x_n,X_k);
	IDFT(X_k,x_n);
}
 
 
//保证N是2的n次幂
int bitlen(int N){
	int n=0;
	while((N&1)==0){
		n++;
		N>>=1;
	}
	return n;
}
 
 
int reverse_bit(int n,int len){//bit反转 
	int tmp=0;
	while(len--){
		tmp+=((n&1)<<len);
		n>>=1;
	}
	return tmp;
 
}
 
//序数重排 
void resort(vector<complex_t> &x_n,int N){
	vector<complex_t> v(x_n);
	int len=bitlen(N);
	for(int i=0;i<N;++i){
		x_n[i]=v[reverse_bit(i,len)];
	}
}
 
 
//基2,FFT算法实现,O(nlogn)的复杂度
void FFT(vector<complex_t> &x_n){
	int N=x_n.size();
	int r=bitlen(N);
	
	vector<complex_t> W(N);
 
	//预先计算旋转因子 
	for(int i=0;i<N;++i){
		double angle=-i*2*PI/N;
		W[i]=complex_t(cos(angle),sin(angle));
	}
	
	
	for(int k=0;k<r;++k){//迭代次数 
		for(int j=0;j<(1<<k);++j){
			int butterfly=1<<(r-k);
			int p=j*butterfly;
			int s=p+butterfly/2;
			for(int i=0;i<butterfly/2;++i){
				complex_t c=x_n[i+p]+x_n[i+s];
				x_n[i+s]=(x_n[i+p]-x_n[i+s])*W[i*(1<<k)];
				x_n[i+p]=c;
			}
		}
	}
	
	//次序重排 
	resort(x_n,N);
	int cnt=0;
	for(int i=0;i<N;++i){
		if(cnt==(int)sqrt(N)){
			cout<<endl;
			cnt=0;
		}
		++cnt;
		cout<<format(x_n[i])<<" ";
		
	}
	cout<<endl;
}
 
//IFFT,与FFT基本一致 
void IFFT(vector<complex_t> &x_n){
	int N=x_n.size();
	int r=bitlen(N);
	
	vector<complex_t> W(N);
 
	//预先计算旋转因子 
	for(int i=0;i<N;++i){
		double angle=i*2*PI/N;//IFFT的旋转因子与FFT的旋转因子差一个负号 
		W[i]=complex_t(cos(angle),sin(angle));
	}
	
	
	for(int k=0;k<r;++k){//迭代次数 
		for(int j=0;j<(1<<k);++j){
			int butterfly=1<<(r-k);
			int p=j*butterfly;
			int s=p+butterfly/2;
			for(int i=0;i<butterfly/2;++i){
				complex_t c=x_n[i+p]+x_n[i+s];
				x_n[i+s]=(x_n[i+p]-x_n[i+s])*W[i*(1<<k)];
				x_n[i+p]=c;
			}
		}
	}
	
	//次序重排 
	resort(x_n,N);
	int cnt=0;
	for(int i=0;i<N;++i){
		if(cnt==(int)sqrt(N)){
			cout<<endl;
			cnt=0;
		}
		++cnt;
		x_n[i]/=N;//IFFT与FFT还差一个系数 
		cout<<format(x_n[i])<<" ";
	}
	cout<<endl;
}
 
void FFT_test(){
	int N=64;
	vector<complex_t> x_n;
	complex_t c(0,0);
	for(int i=0;i<N;++i){
		c.real()=i;
		x_n.push_back(c);
	}
	
	FFT(x_n);
	IFFT(x_n);
}
 
 
int main(){
	DFT_test();
	cout<<endl;
	FFT_test();
	return 0;
}

运行结果与Python的scipy库中的fft算法运行结果对比,基本验证了该算法的正确性:


版权声明:本文为lovemylife1234原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。