FFT:
这里使用基二FFT算法,非基二FFT难度有点大,等以后补充。
对于非2的幂次方长度的序列,我们采用的是补零法:即:我们的FFT只能用于分析或者产生频谱,而不能求得某一特定点的DFT。
首先定义复数操作,实际上,复数操作的定义非常繁琐,这里我只定义了在本次应用中能用到的操作:
const double PI=3.1415926;
const double prec=0.00001;//控制精度
const char MARK='j';//复数的标志符,工程上喜欢使用j,数学上喜欢使用i
//下面是复数结构,主要定义了加减乘除操作符
template
class complex
{
public:
T real;
T imag;
public:
complex(T a=T(),T b=T()):real(a),imag(b){ }
//copy和copy assigment,析构函数可以使用编译器合成的
public:
inline complex conjugate()const;
inline T module() const;
public:
inline complex& operator/=(int rhs);
};
template
complex operator+(const complex& lhs,const complex& rhs)
{
return complex(lhs.real+rhs.real,lhs.imag+rhs.imag);
}
template
complex operator+(const int& lhs,const complex& rhs)
{
return complex(lhs+rhs.real,rhs.imag);
}
template
complex operator+(const complex& lhs,const int& rhs)
{
return complex(lhs.real+rhs,lhs.imag);
}
template
complex operator+(const double& lhs,const complex& rhs)
{
return complex(lhs+rhs.real,rhs.imag);
}
template
complex operator+(const complex& lhs,const double& rhs)
{
return complex(lhs.real+rhs,lhs.imag);
}
template
complex operator+(const T& lhs,const complex& rhs)
{
return complex(lhs+rhs.real,rhs.imag);
}
template
complex operator+(const complex& lhs,const T& rhs)
{
return complex(lhs.real+rhs,lhs.imag);
}
//---------------------------------------------------------------------------
template
complex operator-(const complex& lhs,const complex& rhs)
{
return complex(lhs.real-rhs.real,lhs.imag-rhs.imag);
}
template
complex operator-(const int& lhs,const complex& rhs)
{
return complex(lhs-rhs.real,-rhs.imag);
}
template
complex operator-(const complex& lhs,const int& rhs)
{
return complex(lhs.real-rhs,lhs.imag);
}
template
complex operator-(const double& lhs,const complex& rhs)
{
return complex(lhs-rhs.real,-rhs.imag);
}
template
complex operator-(const complex& lhs,const double& rhs)
{
return complex(lhs.real-rhs,lhs.imag);
}
template
complex operator-(const T& lhs,const complex& rhs)
{
return complex(lhs-rhs.real,-rhs.imag);
}
template
complex operator-(const complex& lhs,const T& rhs)
{
return complex(lhs.real-rhs,lhs.imag);
}
//---------------------------------------------------------------------------
template
complex operator*(const complex& lhs,const complex& rhs)
{
return
complex(lhs.real*rhs.real-lhs.imag*rhs.imag,lhs.real*rhs.imag+lhs.imag*rhs.real);
}
template
complex operator*(const int& lhs,const complex& rhs)
{
return complex(lhs*rhs.real,lhs*rhs.imag);
}
template
complex operator*(const complex& lhs,const int& rhs)
{
return complex(lhs.real*rhs,lhs.imag*rhs);
}
template
complex operator*(const double& lhs,const complex& rhs)
{
return complex(lhs*rhs.real,lhs*rhs.imag);
}
template
complex operator*(const complex& lhs,const double& rhs)
{
return complex(lhs.real*rhs,lhs.imag*rhs);
}
template
complex operator*(const T& lhs,const complex& rhs)
{
return complex(lhs*rhs.real,lhs*rhs.imag);
}
template
complex operator*(const complex& lhs,const T& rhs)
{
return complex(lhs.real*rhs,lhs.imag*rhs);
}
//--------------------------------------------------------------------------------
template
complex operator/(const complex& lhs,const complex& rhs)
{
complex tmp=lhs*rhs.conjugate();
double tmp2=rhs.module();
return complex(tmp.real/tmp2,tmp.imag/tmp2);
}
template
complex operator/(const int& lhs,const complex& rhs)
{
complex tmp=lhs*rhs.conjugate();
double tmp2=rhs.module();
return complex(tmp.real/tmp2,tmp.imag/tmp2);
}
template
complex operator/(const complex& lhs,const int& rhs)
{
return complex(lhs.real/rhs,lhs.imag/rhs);
}
template
complex operator/(const double& lhs,const complex& rhs)
{
complex tmp=lhs*rhs.conjugate();
double tmp2=rhs.module();
return complex(tmp.real/tmp2,tmp.imag/tmp2);
}
template
complex operator/(const complex& lhs,const double& rhs)
{
return complex(lhs.real/rhs,lhs.imag/rhs);
}
template
complex operator/(const T& lhs,const complex& rhs)
{
complex tmp=lhs*rhs.conjugate();
double tmp2=rhs.module();
return complex(tmp.real/tmp2,tmp.imag/tmp2);
}
template
complex operator/(const complex& lhs,const T& rhs)
{
return complex(lhs.real/rhs,lhs.imag/rhs);
}
//---------------------------------------------------------------------------
template
inline bool operator==(const complex& lhs,const complex& rhs)
{
return (lhs.real==rhs.real)&&(lhs.imag==rhs.imag);
}
template
inline bool operator!=(const complex& lhs,const complex& rhs)
{
return !(lhs==rhs);
}
//------------------------------------------------------------------------------
template
std::ostream& operator<<(std::ostream& os,const complex& rhs)
{
if(rhs.imag<0){
os< inline complex complex::conjugate()const {return complex(real,-imag);}
template inline T complex::module() const{return ((*this)*(this->conjugate())).real;}
template inline complex& complex::operator/=(int rhs){*this=(*this)/rhs;return(*this);}
//检查n是否是2的幂次方
bool is_2_pow(int n)
{
if(n<=1){
return false;
}else{
//若n为2^k,则二进制中,只有n的最高位为1,其余为0
for(;(n&1)==0;n>>=1);
if(n==1)return true;
else return false;
}
}
//采用补零法转化至2的幂次方
int padding(int n)
{
if(n<=1){
return 2;
}else{
int digits=(int)(log(n)/log(2))+1;
return (1<<(digits));
}
}
//对于长度为2^digitts的数组,求k的位逆序
int rev(int k,int digits)
{
int result=0;
for(int i=0;i
//如果按位逆序输入数组,那么得到的是正确顺序的DFT
template
void bit_inverse_copy(T1* a,T2* A,int length)
{
int digits=(int)(log(length)/log(2));
for(int i=0;i
bool FFT(T1* a,T2* A,int length,bool inverse=false)//inverse为true表示傅里叶逆变换
{
if(!is_2_pow(length)) return false;//长度不是2的幂次方
int inver=-1;
if(inverse) inver=1;
bit_inverse_copy(a,A,length);
int digit=int(log(length)/log(2));//递归树的层数
for(int s=1;s<=digit;++s){//外层循环,
int m=(int)pow(2,s);//当s确定时,此时进行两个大小为m/2个数组进行蝶形操作
//w=e^-2PIj/m时进行离散傅里叶变换,w=e^2PIj/m进行逆变换
T2 w_m=T2(cos(2*PI*inver/m),sin(2*PI*inver/m));
for(int k=0;k
bool RFFT(T1* a,complex* A,int length,bool inverse=false)
{
int inver=-1;
if(inverse) inver=1;
int half_length=length/2;
complex* z=new complex[half_length];
//x1(n)=a(2n),x2=a(2n+1),z(n)=x1(n)+jx2(n)
for(int i=0,j=0;i* Z=new complex[half_length];
FFT(z,Z,half_length);
//此时有 X1(k)=1/2[Z(k)+Z*(N-k)],X2(k)=1/2j[Z(k)-Z*(N-k)];
//其中Z*代表Z的共轭,N代表Z的长度,当k=0时,N-k=N=0
complex w_2m=complex(cos(2*PI*inver/length),sin(2*PI*inver/length));
complex w(1);
complex X1_k,X2_k;//辅助变量
complex unit_imag=complex(0,1);//大小为j
//此时A[k]=X1[k]+W{k,2N}X2[k],A[k+N]=X1[k]-W{k,2N}X2[k]
for(int k=0;k
有X1(k)=1/2[X(k)+X*(N-k)], X2(k)=1/(2j)[X(k)-X*(N-k)] (其中X*代表X的共轭),于是我们有:
G(k)=X1(k)+W{k,2N}X2(k), G(k+N)=X1(k)-W{k,2N}X2(k)
下面是迭代器版的FFT,可以使用容器装序列:
//如果按位逆序输入数组,那么得到的是正确顺序的DFT
template
void bit_inverse_copy(RandomIter1 _s_beg,RandomIter1 _s_end,RandomIter2 _d_beg,RandomIter2 _d_end)
{
size_t length=_s_end-_s_beg;
int digits=(int)(log(length)/log(2));
for(int i=0;i
bool FFT(RandomIter1 _s_beg,RandomIter1 _s_end,RandomIter2 _d_beg,RandomIter2 _d_end,bool inverse=false)//inverse为true表示傅里叶逆变换
{
typedef typename iterator_traits::value_type T2;
int length=_s_end-_s_beg;
if(!is_2_pow(length)) return false;//长度不是2的幂次方
int inver=-1;
if(inverse) inver=1;
bit_inverse_copy(_s_beg,_s_end,_d_beg,_d_end);
int digit=int(log(length)/log(2));//递归树的层数
for(int s=1;s<=digit;++s){//外层循环,
int m=(int)pow(2,s);//当s确定时,此时进行两个大小为m/2个数组进行蝶形操作
//w=e^-2PIj/m时进行离散傅里叶变换,w=e^2PIj/m进行逆变换
T2 w_m=T2(cos(2*PI*inver/m),sin(2*PI*inver/m));
for(int k=0;k
bool RFFT(RandomIter1 _s_beg,RandomIter1 _s_end,RandomIter2 _d_beg,RandomIter2 _d_end,bool inverse=false)
{
typedef typename iterator_traits::value_type T2;
int length=_s_end-_s_beg;
int inver=-1;
if(inverse) inver=1;
int half_length=length/2;
T2* z=new T2[half_length];
//x1(n)=a(2n),x2=a(2n+1),z(n)=x1(n)+jx2(n)
for(int i=0,j=0;i
int main()
{
ifstream in("E:\\file.txt");
vector vc;
float tmp;
while(in>>tmp){
vc.push_back(tmp);
}
in.close();
int oldsize=vc.size();
int newsize=0;
if(!is_2_pow(vc.size())){
newsize=padding(oldsize);
}else
newsize=oldsize;
for(int i=oldsize;i* h=new complex[newsize];
RFFT(vc.begin(),vc.end(),h,h+newsize);
ofstream out("E:\\file_fft.txt");
out.precision(4);
out<