FFT的计算机实现.docx

上传人:b****5 文档编号:8203045 上传时间:2023-01-29 格式:DOCX 页数:13 大小:186.67KB
下载 相关 举报
FFT的计算机实现.docx_第1页
第1页 / 共13页
FFT的计算机实现.docx_第2页
第2页 / 共13页
FFT的计算机实现.docx_第3页
第3页 / 共13页
FFT的计算机实现.docx_第4页
第4页 / 共13页
FFT的计算机实现.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

FFT的计算机实现.docx

《FFT的计算机实现.docx》由会员分享,可在线阅读,更多相关《FFT的计算机实现.docx(13页珍藏版)》请在冰豆网上搜索。

FFT的计算机实现.docx

FFT的计算机实现

快速傅立叶变换(FFT)的计算机实现

邓凯电气0706

1.FFT运算的原理

DFT运算过程中如果有限长序列的长度很长时,即N很大时,在运算过程中所做的乘法和加法运算将很多。

即便是采用高速的计算机进行运算,也很难达到信息实时处理的要求。

由库利、图基等科学家提出的快速傅里叶变换FFT算法大大减少了运算过程中的乘法和加法次数,适合信息处理对实时性的要求,从而得到广泛应用。

按时间抽取的FFT算法的基本思想是将输入的有限长序列首先分成奇数序列和偶数序列,分别计算出奇、偶序列的DFT,然后根据DFT的周期性和对称性质,将其化简,接着将已分成的奇、偶序列再次分别划分成奇、偶序列,即前面的奇序列按其长度再划分成奇数序列和偶数序列;前面的偶序列按其长度再划分成奇数序列和偶数序列。

分别计算其DFT后,再按上述方法进行化简。

如此反复,直至被划分成的奇、偶序列长度为1为止。

1.1基二FFT算法原理

若设X(k)=DFT[x(n)],且0≤n,k≤N-1,N为偶数(如果N为奇数,则添上一个零值点使长度N为偶数)。

把它分为奇序列和偶序列:

则有

其中,

分别是

点DFT

即要求

的值仅仅只需要求

部分的值即可。

这样,我们就可以将

一直分为奇序列和偶序列来求其值,直到奇偶序列长度为1为止。

1.2蝶形图

对于FFT运算,我们通常用蝶形图来表示

比如

我们表示为

下面以N=8为例,运用FFT算法原理计算DFT,如图1.22、图1.23、图1.24所示。

1.3FFT算法特点

(1)原位运算。

从图2.9的FFT运算流图中我们可以看出,这种运算是很有规律可循的。

其中的每级(每列)运算都是由N/2个蝶形运算所构成,如式(1.31)所示。

(式1.31)

其中,m表示第m列迭代,k,j表示数据所在的行数,该式所对应的蝶形运算结构如图1.31所示。

由图1.31的流程图我们可以看出,对于任一个蝶形中的任何两个节点k和j,经过运算后所得的结果作为下一列(级)k,j两个节点的节点变量,同其他节点变量无关,这样就可以采用原位运算方法。

即某一列的N个数据送入存储器经蝶形运算后,结果为另一级(列)数据,而这些数据结果可以以蝶形为单位仍然存储在这同一组存储器中,直到最后输出,中间无需另加存储器。

也就是说,蝶形运算的两个输出值仍放回到蝶形的两个输入所在的存储器中(即将原先的输入值覆盖掉)。

前一级蝶形运算完成后才进行下一级蝶形原位运算,因而整个运算结

构由于采用这种原位运算而大大减少了存储单元的个数,有效地降低了成本。

(2)倒位序规律。

由图2.9我们还可看出,由于采用了原位计算方法,FFT的输出X(k)是按k值的自然顺序排列在存储单元中的,即排列序列为X(0),X

(1),…,X(7),而输入的时间序列都不是按照自然顺序排列,而是按x(0),x(4),x

(2),…,x(7),输入到存储单元中。

这种排列初看起来像是“混乱无序”的,但实质是有序的。

如果我们用二进制数来表示0~7个数,设为n(n2n1n0)2,然后再来观察n(n0n1n2)2,如表1.1所示。

十进制数

二进制数

二进制数

十进制数

0

000

000

0

1

001

100

4

2

010

010

2

3

011

110

6

4

100

001

1

5

101

101

5

6

110

011

3

7

111

111

7

由表我们可以看出,只要将

转换成

,即将二进制的最高位与最低位相交换、次高位与次低位相交换……所得的n就是以自然顺序排列的,故通常n的这种排列规律我们称之为倒位序。

这两条性质给我们编程带来了极大的方便。

2.C语言实现FFT算法

2.1算法基本原理

如上所述,FFT算法给编程带来了极大大方便,对比于DFT不仅运算次数大大降低,就连所需的内存空间在运算中也不会增加。

主要算法有两部分,一个是倒二进制排序,还有最重要的蝶形算法。

倒二进制算法

对数组下标进行倒二进制运算,把输入数组按倒二进制排序即可,算法很简单,具体可参见代码

蝶形算法

核心即为如下公式,只需进行几次循环分级进行蝶形算法即可,具体可参见代码。

2.2程序流程图

其中的N表示运算的总级数,即将FFT时域序列分出奇偶序列,直至每个序列点数为1所需的次数。

若有1024个点,则N为10。

3.FFT的Matlab实验

3.1改变序列的长度N对计算结果的影响

x=0.5sin(2*pi*15*t)+2*sin(2*pi*40*t)。

采样频率fs=100Hz,分别绘制N=128、1024点幅频图。

在Matlab中输入如下代码:

>>clf;

fs=100;N=128;%采样频率和数据点数

n=0:

N-1;t=n/fs;%时间序列

x=0.5*sin(2*pi*15*t)+2*sin(2*pi*40*t);%信号

y=fft(x,N);%对信号进行快速Fourier变换

mag=abs(y);%求得Fourier变换后的振幅

f=n*fs/N;%频率序列

subplot(2,2,1),plot(f,mag);%绘出随频率变化的振幅

xlabel('频率/Hz');

ylabel('振幅');title('N=128');gridon;

subplot(2,2,2),plot(f(1:

N/2),mag(1:

N/2));%绘出Nyquist频率之前随频率变化的振幅

xlabel('频率/Hz');

ylabel('振幅');title('N=128');gridon;

%对信号采样数据为1024点的处理

fs=100;N=1024;n=0:

N-1;t=n/fs;

x=0.5*sin(2*pi*15*t)+2*sin(2*pi*40*t);%信号

y=fft(x,N);%对信号进行快速Fourier变换

mag=abs(y);%求取Fourier变换的振幅

f=n*fs/N;

subplot(2,2,3),plot(f,mag);%绘出随频率变化的振幅

xlabel('频率/Hz');

ylabel('振幅');title('N=1024');gridon;

subplot(2,2,4)

plot(f(1:

N/2),mag(1:

N/2));%绘出Nyquist频率之前随频率变化的振幅

xlabel('频率/Hz');

ylabel('振幅');title('N=1024');gridon;

>>

x=0.5*sin(2*pi*15*t)+2*sin(2*pi*40*t)。

采样频率fs=100Hz,当N=128、1024点幅频图如下

fs=100Hz,Nyquist频率为fs/2=50Hz。

整个频谱图是以Nyquist频率为对称轴的。

并且可以明显识别出信号中含有两种频率成分:

15Hz和40Hz。

由此可以知道FFT变换数据的对称性。

因此用FFT对信号做谱分析,只需考察0~Nyquist频率范围内的福频特性。

若没有给出采样频率和采样间隔,则分析通常对归一化频率0~1进行。

另外,振幅的大小与所用采样点数有关,采用128点和1024点的相同频率的振幅是有不同的表现值,但在同一幅图中,40Hz与15Hz振动幅值之比均为4:

1,与真实振幅0.5:

2是一致的。

为了与真实振幅对应,需要将变换后结果乘以2除以N。

由上图可得,点数取得越多,由FFT所得的频谱越精确。

4.总结

傅里叶变换在物理学、数论、组合数学、信号处理、概率论、统计学、密码学、声学、光学、海洋学、结构动力学等领域都有着广泛的应用(例如在信号处理中,傅里叶变换的典型用途是将信号分解成幅值分量和频率分量)。

而FFT则实现了傅里叶变换在计算机领域的广泛应用,学习FFT的原理和实现,对后续课程如电力系统的分析等是很有必要的。

本次课程设计,我选择了FFT在计算机上的实现这一个题目,采用C语言编程实现FFT算法,同时用Matlab对C程序进行验证和分析。

在完成课设过程中,不仅弄清楚了FFT的原理,还学到了Matlab相关的知识,C语言编程能力也得到了较大的提高。

附录程序清单

1.1复数的算法

#include"complex.h"

CComplex:

:

CComplex(void)

{

Realpart=0;

ImagPart=0;

}

CComplex:

:

CComplex(doubleReal,doubleImag)

{

Realpart=Real;

ImagPart=Imag;

}

CComplex:

:

CComplex(doublereal)

{

Realpart=real;

ImagPart=0;

}

CComplex:

:

~CComplex(void)

{

}

/////////////////////////////////////////////////////////////////////////////////

/*重载数学运算符*/

/////////////////////////////////////////////////////////////////////////////////

//+重载

CComplexCComplex:

:

operator+(CComplexOtherComplex)

{

CComplextemp;

temp.Realpart=Realpart+OtherComplex.Realpart;

temp.ImagPart=ImagPart+OtherComplex.ImagPart;

returntemp;

}

//-重载

CComplexCComplex:

:

operator-(CComplexOtherComplex)

{

CComplextemp;

temp.Realpart=Realpart-OtherComplex.Realpart;

temp.ImagPart=ImagPart-OtherComplex.ImagPart;

returntemp;

}

//*重载

CComplexCComplex:

:

operator*(CComplexOtherComplex)

{

CComplextemp;

temp.Realpart=Realpart*OtherComplex.Realpart-ImagPart*OtherComplex.ImagPart;

temp.ImagPart=Realpart*OtherComplex.ImagPart+ImagPart*OtherComplex.Realpart;

returntemp;

}

1.2FFT运算

#include"complex.h"

#defineFFTPOINT8

//////////////////////////////////////////////////////////////////////////////////////

/*输入时域取样数据*/

voidInPut(double*pData)

{

doubleIpt;

for(inti=0;i

{

cin>>Ipt;

*(pData+i)=Ipt;

}

}

/*输出变换后的频域数据,复数形式*/

voidOutput(CComplex*pData)

{

CComplexOut;

cout<<"FFT变换后,频域数据为"<

for(inti=0;i

{Out=*(pData+i);

if((Out.Realpart)>=0)

{

printf("%.4fj+%.4f\n",Out.ImagPart,Out.Realpart);

}

else

{

printf("%.4fj%.4f\n",Out.ImagPart,Out.Realpart);

}

}

}

///////////////////////////////////////////////////////////////////////////////////////

/*将输入的数据按倒二进制排序*/

voidFFTArry(double*pData1,CComplex*pData2)

{

inti=0,m=2,t=0;

for(N=0;m<=FFTPOINT;N++)

{

m*=2;

}

for(i=0;i

{

inttemp=i;

t=0;

for(intj=N-1;j>=0;j--)

{

if(temp/(int)(pow(2,j)))

t+=pow(2,N-j-1);

temp=temp%(int)(pow(2,j));

}

pData2[t].Realpart=*(pData1+i);

}

}

////////////////////////////////////////////////////////////////////////////////////////////////////

externintN=0;

voidmain()

{

voidFFT(CComplex*pData);

doubleFFTDataIn[FFTPOINT]={0.0};

CComplexFFTDataOut[FFTPOINT];

cout<<"请输入原数据,最大个数为:

"<

InPut(FFTDataIn);//输入数据

FFTArry(FFTDataIn,FFTDataOut);//将输入数据按到二进制排序

FFT(FFTDataOut);//进行FFT变换

Output(FFTDataOut);//输出

}

///////////////////////////////////////////////////////////////////////////////////////

voidFFT(CComplex*pData)

{

inti,r,steplen,k,j;

for(i=0;i

{

steplen=(int)(pow(2,i));/*计算步长*/

for(r=0;r

{

CComplexW(cos(2*PI*r/pow(2,i+1)),-sin(2*PI*r/pow(2,i+1)));/*旋转因子的值*/

for(j=0;j<(FFTPOINT/pow(2,i+1));j++)/*r相同的值的组的计算*/

{

CComplextemp1,temp2;

k=(int)(r+j*pow(2,i+1));/*每一组成员的下标*/

temp1=pData[k]+W*pData[k+steplen];

temp2=pData[k]-W*pData[k+steplen];

pData[k]=temp1;

pData[k+steplen]=temp2;

}

}

}

}

//////////////////////////////////////////////////////////////////////////////////////////////////

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > 财会金融考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1