FFT的计算机实现Word下载.docx

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

FFT的计算机实现Word下载.docx

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

FFT的计算机实现Word下载.docx

一直分为奇序列和偶序列来求其值,直到奇偶序列长度为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所示。

十进制数

二进制数

十进制数

000

1

001

100

4

2

010

3

011

110

6

5

101

7

111

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

转换成

,即将二进制的最高位与最低位相交换、次高位与次低位相交换……所得的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频率之前随频率变化的振幅

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

N=1024;

%求取Fourier变换的振幅

subplot(2,2,3),plot(f,mag);

N=1024'

subplot(2,2,4)

plot(f(1:

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(doubleReal,doubleImag)

Realpart=Real;

ImagPart=Imag;

CComplex(doublereal)

Realpart=real;

~CComplex(void)

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

/*重载数学运算符*/

//+重载

CComplexCComplex:

operator+(CComplexOtherComplex)

CComplextemp;

temp.Realpart=Realpart+OtherComplex.Realpart;

temp.ImagPart=ImagPart+OtherComplex.ImagPart;

returntemp;

//-重载

operator-(CComplexOtherComplex)

temp.Realpart=Realpart-OtherComplex.Realpart;

temp.ImagPart=ImagPart-OtherComplex.ImagPart;

//*重载

operator*(CComplexOtherComplex)

{

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

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

1.2FFT运算

#defineFFTPOINT8

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

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

voidInPut(double*pData)

doubleIpt;

for(inti=0;

i<

FFTPOINT;

i++)

{

cin>

Ipt;

*(pData+i)=Ipt;

}

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

voidOutput(CComplex*pData)

CComplexOut;

cout<

<

"

FFT变换后,频域数据为"

endl;

for(inti=0;

i++)

{Out=*(pData+i);

if((Out.Realpart)>

=0)

{

printf("

%.4fj+%.4f\n"

Out.ImagPart,Out.Realpart);

}

else

%.4fj%.4f\n"

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

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

voidFFTArry(double*pData1,CComplex*pData2)

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

for(N=0;

m<

=FFTPOINT;

N++)

m*=2;

for(i=0;

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

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

FFTPOINT<

InPut(FFTDataIn);

//输入数据

FFTArry(FFTDataIn,FFTDataOut);

//将输入数据按到二进制排序

FFT(FFTDataOut);

//进行FFT变换

Output(FFTDataOut);

//输出

voidFFT(CComplex*pData)

inti,r,steplen,k,j;

for(i=0;

N;

i++)/*实现N级运算*/

steplen=(int)(pow(2,i));

/*计算步长*/

for(r=0;

r<

pow(2,i);

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