快速傅里叶变换C++递归算法实现
网上有些算法资料经测试运行结果是错误的,虽然代码的使用的是非递归形式。为了方便验证快速傅里叶变换的准确性,我提供了自己设计的递归算法。
基于时域抽取的“基2”快速傅里叶变换算法代码:
Fouier.h文件:
#pragma once
#include " Complex.h "
class Fouier
{
Complex * data;
void fft( int start, int step, int len);
Complex W( int k, int n); // e^(-i*2*pi*k/n)
public:
Fouier( void);
~Fouier( void);
void fft();
};
#include " Complex.h "
class Fouier
{
Complex * data;
void fft( int start, int step, int len);
Complex W( int k, int n); // e^(-i*2*pi*k/n)
public:
Fouier( void);
~Fouier( void);
void fft();
};
Fouier.c文件:
#include
"
Fouier.h
"
#include<iostream>
using namespace std;
#include<cmath>
#include<ctime>
#define DATALEN 32
#define KEYVALUE 10000 // 生成随机浮点数的值,保证分子和分母在这个值之内
#define PI 3.14159265358979323846
Fouier::Fouier( void)
{
data= new Complex[DATALEN];
srand(unsigned int(time( 0)));
cout<< " 源数据: "<<endl;
for( int i= 0;i<DATALEN;i++)
{
data[i]=(rand()%(KEYVALUE))/( double)(rand()%(KEYVALUE)+ 1);
if(i% 5== 0&&i!= 0)
cout<<endl;
cout<<data[i]<< " ";
}
cout<<endl;
}
Fouier::~Fouier( void)
{
delete [] data;
}
Complex Fouier:: W( int k, int n) // 欧拉公式
{
double alpha=- 2*PI*k/n;
return Complex(cos(alpha),sin(alpha));
}
void Fouier::fft( int start, int step, int len)
{
if(len== 1) // 一个元素
{
// 一个元素不需要变换
return ;
}
fft(start,step* 2,len/ 2); // X1(k)
fft(start+step,step* 2,len/ 2); // X2(k)
Complex X1,X2;
for( int i= 0;i<len/ 2;i++)
{
X1=data[start+step*i* 2];
X2=data[start+step*(i* 2+ 1)];
// 计算X(k):k=0~N/2-1
data[start+step*i]=X1+W(i,len)*X2;
// 计算X(k):k=N/2~N-1
data[start+step*(i+len/ 2)]=X1-W(i,len)*X2;
}
}
void Fouier::fft()
{
fft( 0, 1,DATALEN);
cout<< " 变换后数据: "<<endl;
for( int i= 0;i<DATALEN;i++)
{
if(i% 5== 0&&i!= 0)
cout<<endl;
cout<<data[i]<< " ";
}
}
#include<iostream>
using namespace std;
#include<cmath>
#include<ctime>
#define DATALEN 32
#define KEYVALUE 10000 // 生成随机浮点数的值,保证分子和分母在这个值之内
#define PI 3.14159265358979323846
Fouier::Fouier( void)
{
data= new Complex[DATALEN];
srand(unsigned int(time( 0)));
cout<< " 源数据: "<<endl;
for( int i= 0;i<DATALEN;i++)
{
data[i]=(rand()%(KEYVALUE))/( double)(rand()%(KEYVALUE)+ 1);
if(i% 5== 0&&i!= 0)
cout<<endl;
cout<<data[i]<< " ";
}
cout<<endl;
}
Fouier::~Fouier( void)
{
delete [] data;
}
Complex Fouier:: W( int k, int n) // 欧拉公式
{
double alpha=- 2*PI*k/n;
return Complex(cos(alpha),sin(alpha));
}
void Fouier::fft( int start, int step, int len)
{
if(len== 1) // 一个元素
{
// 一个元素不需要变换
return ;
}
fft(start,step* 2,len/ 2); // X1(k)
fft(start+step,step* 2,len/ 2); // X2(k)
Complex X1,X2;
for( int i= 0;i<len/ 2;i++)
{
X1=data[start+step*i* 2];
X2=data[start+step*(i* 2+ 1)];
// 计算X(k):k=0~N/2-1
data[start+step*i]=X1+W(i,len)*X2;
// 计算X(k):k=N/2~N-1
data[start+step*(i+len/ 2)]=X1-W(i,len)*X2;
}
}
void Fouier::fft()
{
fft( 0, 1,DATALEN);
cout<< " 变换后数据: "<<endl;
for( int i= 0;i<DATALEN;i++)
{
if(i% 5== 0&&i!= 0)
cout<<endl;
cout<<data[i]<< " ";
}
}
Complex.h文件:
#pragma once
#include<iostream>
using namespace std;
class Complex // a+b*i
{
double a; // 实数部分
double b; // 虚数部分
public:
Complex( double a= 0, double b= 0);
// +操作
friend Complex operator +(Complex &x,Complex &y);
friend Complex operator +( double x,Complex &y);
friend Complex operator +(Complex &x, double y);
// -操作
friend Complex operator -(Complex &x,Complex &y);
friend Complex operator -( double x,Complex &y);
friend Complex operator -(Complex &x, double y);
// *操作
friend Complex operator *(Complex &x,Complex &y);
friend Complex operator *( double x,Complex &y);
friend Complex operator *(Complex &x, double y);
// =操作
Complex operator =(Complex &x);
Complex operator =( double x);
// <<操作
friend ostream & operator<<(ostream& out,Complex&c);
~Complex( void);
};
#include<iostream>
using namespace std;
class Complex // a+b*i
{
double a; // 实数部分
double b; // 虚数部分
public:
Complex( double a= 0, double b= 0);
// +操作
friend Complex operator +(Complex &x,Complex &y);
friend Complex operator +( double x,Complex &y);
friend Complex operator +(Complex &x, double y);
// -操作
friend Complex operator -(Complex &x,Complex &y);
friend Complex operator -( double x,Complex &y);
friend Complex operator -(Complex &x, double y);
// *操作
friend Complex operator *(Complex &x,Complex &y);
friend Complex operator *( double x,Complex &y);
friend Complex operator *(Complex &x, double y);
// =操作
Complex operator =(Complex &x);
Complex operator =( double x);
// <<操作
friend ostream & operator<<(ostream& out,Complex&c);
~Complex( void);
};
Complex.c文件:
#include
"
Complex.h
"
Complex::Complex( double a, double b) // 虚部默认是0
{
this->a=a;
this->b=b;
}
Complex::~Complex( void)
{
}
Complex operator +(Complex &x,Complex &y)
{
return Complex(x.a+y.a,x.b+y.b);
}
Complex operator +( double x,Complex &y)
{
return Complex(x+y.a,y.b);
}
Complex operator +(Complex &x, double y)
{
return Complex(x.a+y,x.b);
}
Complex operator -(Complex &x,Complex &y)
{
return Complex(x.a-y.a,x.b-y.b);
}
Complex operator -( double x,Complex &y)
{
return Complex(x-y.a,-y.b);
}
Complex operator -(Complex &x, double y)
{
return Complex(x.a-y,x.b);
}
Complex operator *(Complex &x,Complex &y)
{
return Complex(x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a);
}
Complex operator *( double x,Complex &y)
{
return Complex(x*y.a,x*y.b);
}
Complex operator *(Complex &x, double y)
{
return Complex(x.a*y,x.b*y);
}
Complex Complex:: operator =(Complex &x)
{
a=x.a;
b=x.b;
return * this;
}
Complex Complex:: operator =( double x)
{
a=x;
b= 0;
return * this;
}
ostream & operator<<(ostream& out,Complex&c)
{
if(c.a!= 0||c.a== 0&&c.b== 0)
out<<c.a;
if(c.b!= 0)
{
if(c.b> 0)
out<< " + ";
if(c.b!= 1)
out<<c.b;
out<< " i ";
}
return out;
}
Complex::Complex( double a, double b) // 虚部默认是0
{
this->a=a;
this->b=b;
}
Complex::~Complex( void)
{
}
Complex operator +(Complex &x,Complex &y)
{
return Complex(x.a+y.a,x.b+y.b);
}
Complex operator +( double x,Complex &y)
{
return Complex(x+y.a,y.b);
}
Complex operator +(Complex &x, double y)
{
return Complex(x.a+y,x.b);
}
Complex operator -(Complex &x,Complex &y)
{
return Complex(x.a-y.a,x.b-y.b);
}
Complex operator -( double x,Complex &y)
{
return Complex(x-y.a,-y.b);
}
Complex operator -(Complex &x, double y)
{
return Complex(x.a-y,x.b);
}
Complex operator *(Complex &x,Complex &y)
{
return Complex(x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a);
}
Complex operator *( double x,Complex &y)
{
return Complex(x*y.a,x*y.b);
}
Complex operator *(Complex &x, double y)
{
return Complex(x.a*y,x.b*y);
}
Complex Complex:: operator =(Complex &x)
{
a=x.a;
b=x.b;
return * this;
}
Complex Complex:: operator =( double x)
{
a=x;
b= 0;
return * this;
}
ostream & operator<<(ostream& out,Complex&c)
{
if(c.a!= 0||c.a== 0&&c.b== 0)
out<<c.a;
if(c.b!= 0)
{
if(c.b> 0)
out<< " + ";
if(c.b!= 1)
out<<c.b;
out<< " i ";
}
return out;
}
main.c文件:
#include<iostream>
using namespace std;
#include " Fouier.h "
int main()
{
Fouier f;
f.fft();
return 0;
}
using namespace std;
#include " Fouier.h "
int main()
{
Fouier f;
f.fft();
return 0;
}
如有错误,欢迎批评指正!
参考资料:http://zhoufazhe2008.blog.163.com/blog/static/63326869200971010421361/
维基百科:http://zh.wikipedia.org/wiki/%E5%BF%AB%E9%80%9F%E5%82%85%E7%AB%8B%E5%8F%B6%E5%8F%98%E6%8D%A2