FFT算法实现与分析MATLAB

article/2025/10/18 22:26:05

FFT算法实现

2.1实验目的

I、加深对快速傅里叶变换的理解。
II、掌握 FFT 算法及其程序的编写。
III、掌握算法性能评测的方法。
IV、熟悉MatLab编程。

2.2实验原理

一个连续信号Xa(t)的频谱可以用它的傅里叶变换表示为:
在这里插入图片描述

如果对该信号进行理想采样,可以得到采样序列:
在这里插入图片描述

同样可以对该序列进行z变换,其中T为采样周期:
在这里插入图片描述

当z=e^jω的时候,我们就得到了序列的傅里叶变换:
在这里插入图片描述

其中w称为数字频率,它和模拟域频域的关系为:
在这里插入图片描述

其中fs是采样频率。上式说明数字频率是模拟频率对采样率 fs 的归一化。同模拟域的情况相似,数字频率代表了序列值变化的速率,而序列的傅立叶变换称为序列的频谱。序列的傅立叶变换和对应的采样信号频谱具有下式的对应关系。
在这里插入图片描述

即序列的频谱是采样信号频谱的周期延拓。从上式可以看出,只要分析采样序列的频谱,就可以得到相应的连续信号的频谱。
在各种信号序列中,有限长序列在数字信号处理中占有很重要的地位。无限长的序列也往往可以用有限长序列来逼近。对于有限长的序列我们可以使用离散傅立叶(DFT),这一变换可以很好地反应序列的频域特性,并且容易利用快速算法在计算机上实现当序列的长度是 N 时,我们定义离散傅立叶变换为:
在这里插入图片描述

其中W_N=e^(-2Πj/N),它的反变换定义为:
在这里插入图片描述

若直接计算DFT变换,整个DFT运算需要4N^2次实数相乘和2N(2N-1)次实数相加。
所以直接计算乘法次数与加法次数都和N^2成正比。例如N=10点的DFT,需要100次复数相乘,而N=1024时则需要1,048,576即一百多万次复数乘法运算。这对于实时性要求很强的信号处理来说,必将对计算速度有十分严苛的要求。为此,FFT作为对DFT的改进诞生。
快速傅里叶变换FFT并不是与DFT不相同的另一种变换,而是在DFT计算规律上建立的一种减少运算次数的快速算法。常用FFT是以基-2的,长度N=2^M。运算效率高,程序简单,使用方便。本实验就使用以2为基实现FFT。算法流程图可以用蝶形算法来表示,以8点的基2-FFT算法为例:
在这里插入图片描述

每个蝶形运算为:
在这里插入图片描述

可以看到,每个蝶形运算都可原位运算。
当需要进行变换的序列长度不是2 的整数次方的时候,为了使用以 2 为基的 FFT,可以用末尾补零的方法,使其长度延长至 2 的整数次方。IFFT一般可以通过 FFT 程序来完成,只要对 X(k)取共轭,进行 FFT 运算,然后再取共轭,并乘以因子 1/N,就可以完成 IFFT。

2.3实验内容

1、算法实现
以对高斯序列进行FFT代码为例:
在这里插入图片描述

①、使用bitrevorder()函数对待变换信号顺序进行调整,存入x1中。例如M=8时
原顺序:000(0),001(1),010(2),011(3),100(4),101(5),110(6),111(7)

对二进制翻转之后为:

新顺序:000(0),100(4),010(2),110(6),001(1),101(5),011(3),111(7)

对比实验原理中M=8的FFT输入序列发现两者顺序一致。
②、n=1:m1表示一共有m1层运算,比如M=8时有3层。
k=1:M/(2^n)表示第n层分为k部分,比如M=8的第一层分为4个单独蝶形运算,第二层分为2个两两蝶形运算,第三部分为1个四四蝶形运算。
m表示第k部分的第m个蝶形运算。
③、因为蝶形运算是原位运算,就不需要另外开辟空间,计算结果仍然存在原位置。
④、绘出编写的FFT计算结果与MATLAB的FFT计算结果,以及两者的差。
2、选取实验 1 中的典型信号序列验证算法的有效性
I、三角波
在这里插入图片描述

II、反三角波
在这里插入图片描述

III、高斯序列
在这里插入图片描述

IV、衰减正弦序列
在这里插入图片描述

V、单位脉冲序列
在这里插入图片描述

VI、矩形窗序列
在这里插入图片描述

VII、理想采样序列
在这里插入图片描述

注意每个序列自己编写的FFT计算结果和MATLAB的FFT计算结果,两者相差数量级
在10(-16)到10(-14)。说明编写的FFT算法正确性没有问题。

3、对所编制的FFT算法进行性能评估
算法的评估首先是其正确性,是否能够完成预期功能决定了该算法是否有意义,
上一部分已经通过典型信号序列验证了编写的FFT算法的有效性。
这里接下来主要从时间复杂度和空间复杂度两方面来进行评价。空间复杂度是指该算法运行过程需要占用多少内存空间,随着半导体产业的发展,内存空间变得越来越廉价,空间复杂度对算法性能的影响也越来越小。人们往往根据时间复杂度来评价一个算法的性能。而时间复杂度主要依赖于算法的计算次数。已知基2-FFT算法的复数乘法次数为1/2 〖Nlog〗_2 N。相比于加法,乘法在运算中要复杂得多,占用资源也更多,所以时间复杂度主要依赖乘法次数。从理论复杂度来看,FFT显然比DFT的N^2更优。在MARLAB中查看程序运算时间有以下办法:

①、tic和toc命令组合
tic;
operation;
toc;
tic用来保存当前时间,也就是operation开始运行时间,toc用来记录程序完成时间。MATLAB会自动计算时间差并显示(以秒为单位但能精确到小数点后6位,即us)。

②、etime(t1,t2)和clock配合
t1=clock;
operation;
t2=clock;
etime(t1,t2);
通过调用windows系统时钟进行时间差计算得到运行时间,t1和t2之间的时间差。

③cputime函数
t1=cputime;
operation;
t2=cputime-t1;
使用cpu主频计算运行时间差,得到程序运行时间。

tic/toc是MATLAB自身计数器,精度要高于后两者。而且,如②调用系统时钟计算时间差,这段时间中系统可能还有其他后台程序。
MATLAB官方推荐使用tic/toc组合,When timing the duration of an event,use the tic and toc functions instead of clock or etime.所以接下来的评估程序运行时间,本实验使用tic/toc命令。此外,程序运行时间和计算机本身的计算能力有着直接关系,以下数据都是在个人笔记本电脑测得。由于电脑属于商务本,计算能力很有限,时间相对会稍长一些。
以上主要说明了FFT算法评估方法和侧重点,具体评估数据在下面的dofft与DFT、dofft与MATLAB-FFT的性能比较中给出。

2.4实验报告要求

1、总结自己实现的FFT算法时采用了哪些方法减少了运算量。
1)使用matlab的bitrevorder()函数实现二进制翻转,由于matlab的函数是基于更底层的的c语言编写的,有很专业的优化,执行速度肯定更快。
2)尽量使用小循环套大循环,因为执行的跳转原因,大循环单次执行时间优于小循环。
3)利用蝶形运算的原位性,使用同一个地址空间存储变换前序列和变换后序列。
4)每相邻计算的蝶形运算数据在地址上尽量连续,减少寻址时间。
2、给出自己的FFT算法与实验1中的DFT算法性能比较结果。
为避免运算时间过短不利于记录,使用20次循环。dofft程序见2.3,其余程序如下
DFT程序:
在这里插入图片描述

dofft测试程序:
在这里插入图片描述

DFT测试程序:
在这里插入图片描述

运行时间记录如下:
N
算法 8 32 256 512 1024 2048
dofft 1.524102 1.563602 1.820989 1.984634 2.814433 3.088558
DFT 0.367555 0.375953 0.945036 4.491770 22.746014 107.771205
作图:
在这里插入图片描述

测试序列为理想采样序列。为避免循环运行时,MATLAB程序在前一循环已在内存中开辟空间和留有数据,测试程序中使用了clear all命令来清除内存中的数据。这样测得的时间更加准确。从记录的运行时间中可以看到,当N比较小的时候,DFT运行时间比dofft时间更小,这是因为DFT算法使用的是向量运算,而dofft中使用了循环。MATLAB本身对于向量计算的速度快于循环的计算速度。所以如果进一步优化dofft算法,可以改用向量运算,避免循环。当N趋于更大时,DFT运行时间迅速上升,很快 和dofft运行时间不在一个数量级。这和DFT、FFT两算法的理论时间复杂度一致。
3、给出自己的FFT算法和MATLAB中fft算法性能比较结果。
采用与2中相同的测试方法,同样使用20次循环。

fft程序:

在这里插入图片描述

fft测试程序:
在这里插入图片描述

运行时间记录如下:
N
算法 512 1024 2048 4096 8192
dofft 1.984634 2.814433 3.088558 3.579388 5.438975
FFT 0.349001 0.369433 0.365632 0.403413 0.334651
N
算法 16384 32768 65536 131072 262144
dofft 13.307104 18.961649 28.585727 61.441558 125.271445
FFT 0.350225 0.431561 0.430717 0.445077 0.530932
作图:
在这里插入图片描述

自己编写的dofft在进行变换长度的横坐标下近似线性增长。而MATLAB本身的FFT基本上随着N的增大,运行时间基本上没有变化。显然dofft性能比fft性能差。想必MATLAB中的fft函数进行了更多技巧和优化。

4、总结实验中根据实验现象得到的其他结论。

①实验中测运行时间,当前后两个程序运行时间相差不大时,可能时间大小有波动。比如MATLAB中的fft函数在做2048点计算时所用时间比1024点计算时间稍小,这与MATLAB当前占CPU和电脑状态相关。也会出现同一个程序在不同时刻测运行时间大小稍有差异,多测几次时间取平均时间长。
②DFT在N较小时运行时间小于dofft,说明MATLAB更优于计算向量。所以编写MATLAB程序时应尽量把for循环改为矩阵运算,尽量向量化。
③同样的算法,基于不同的编程,在运行速度上仍然会有很大的不同,比如在MATLAB中使用for循环编写,MATLAB本身的FFT,和用C语言编写的FFT在运行速度上都会有很大不同。所以提高编程技巧,了解程序具体流水线、地址开辟、循环嵌套等等如何对优化程序有很大意义。
④MATLAB带有众多功能强大,高优化水平的函数,在编写程序时,尽可能查询MATLAB有无相关函数,充分利用,以提高编写的程序的执行效率,比如dofft中的bitreorder。
⑤测量运行时间的时候要把绘图的函数注释掉,否者会占用程序大量运行时间。


http://chatgpt.dhexx.cn/article/hN51SmK1.shtml

相关文章

采用FPGA实现FFT算法

关注、星标公众号,精彩内容每日送达 来源:网络素材 随着数字技术的快速发展,数字信号处理已深入到各个学科领域。在数字信号处理中,许多算法如相关、滤波、谱估计、卷积等都可通过转化为离散傅立叶变换(DFT)实现,从而为…

[笔记]FFT算法

前言 对于学通信的人来说,在学到数字信号处理时都会学到一个东东,叫做快速傅里叶变换(Fast Fourier Transform,简称FFT)。这东西真的挺有用的,但是只要有那么一点用的东西,就是特别难的。(现在也有很多不完整的地方,以…

c语言实现fft原理,新手小白一看就会,FFT算法的原理详解

原标题:新手小白一看就会,FFT算法的原理详解 相信网上现在有很多关于FFT的教程,我曾经也参阅了很多网上的教程,感觉都不怎么通俗易懂。在基本上的研究FFT,并且通过编程的形式实现之后。我决定写一篇通俗易懂的关于FFT的讲解。因此我在接下来的叙述中尽量非常通俗细致的讲解…

FFT算法实现,python,Java

FFT算法实践报告 FFT基本原理 代码链接: link. DFT 在讨论FFT之前,我们需要先了解以下DFT。所谓的DFT其实就是两个矩阵做点乘。 多项式可以有两种表示方法,一种是系数表示法,另一种是点值表示法。 这两种表示法之间是可以转换的&#xff…

MATLAB FFT算法的应用

目录 一,实验原理 二,实验内容 1、实现2N点实数序列 2、已知某序列​编辑在单位圆上的N64等分样点的Z变换为: 3、周期为N的余弦序列: 1,求该序列N点FFT 2,求该序列2N点FFT 3,求该序列N/2点…

FFT算法实现

关于FFT算法的原理这里就不多说了,具体参考有关书籍。 DFT与FFT运算量的比较 N点DFT的运算量 复数乘法 复数加法 一个X(k) N N-1 N个X(k)(N点DFT) N*N N(N-1) N点FFT的运算量 复数乘法 复数加法 N个X(k) (N/2)*log2N N*log2N 如…

使用python手写FFT算法

FFT(Fast Fourier Transform) 是 DFT(Discrete Fourier Transform)的快读实现,它在机理上没有改变DFT的算法,只是在实现上采用的巧妙的实现。 使 O ( N 2 ) O(N^2) O(N2)的实现变成了 O ( N l o g 2 N ) O(Nlog_2N) O(Nlog2​N)的实现,优化算…

C语言实现FFT算法

C语言实现FFT算法 fft1d.c和fft1d.h见https://download.csdn.net/download/weixin_43216875/12009644 1 fft1d.h #ifndef FFT1D_H #define FFT1D_H#include "math.h"#define PI 3.1415926535897932384626433832795028841971typedef struct complex //复数类型 {flo…

Matlab实现DITFFT算法

这段时间刚好在学习数字信号处理的快速傅立叶变换,也刚好应着老师布置的作业用matlab实现N点的FFT。 方法也是采用教科书上的DITFFT,当然关键也就是分治的思想,分成奇偶序列,再观察旋转因子和步长的不同来编写算法 该算法首先的部…

FFT算法的C语言实现

FFT算法的C语言实现 :数字信号处理 需要注意的几个点 #mermaid-svg-Q0Cv61uzu3GVxhM0 .label{font-family:trebuchet ms, verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-Q0Cv61uzu3GVxhM0 .label text{fill:#333}#mer…

优雅的FFT算法

简 介: 利用FFT算法实现快速傅里叶变换, 在理论、工程中具有非常广泛的应用。 除了能够在合适的计算平台完成FFT算法,同时还需要注意到它在频谱分析中可能带来的频率混叠以及频率泄露等问题。 关键词: FFT,算法实现 #m…

STM32 FFT算法实现

DSP 库运行环境搭建 在 MDK 里面搭建 STM32F4 的 DSP 运行环境(使用.lib 方式)是很简单的,分为 3 个步骤: 1, 添加文件。 首先,我们在例程工程目录下新建:DSP_LIB 文件夹,存放我们将要添加的文件&#xff…

FFT算法解析

问题描述 两个n次多项式相乘,其时间复杂度为 O(n2) ,通过FFT来减小其问题的复杂度。 分析过程 FFT的基本思路是:我知道一个多项式表达式可以根据其表达式算出结果,同理我们也可以根据其结果算出表达式。对于A,B两个n次多项式,一共所有又2n+1个参数需要求解,我们至少需要…

FFT算法再学以及终于理解

前言 人生如逆旅,我亦是行人。 一、FFT FFT(Fast Fourier Transformation),中文名快速傅里叶变换,用来 加速多项式乘法 ,就是用来降低算法的时间复杂度的,将时间复杂度由原来的 O(n^2) 变为了O…

十分简明易懂的FFT(快速傅里叶变换)

FFT前言 快速傅里叶变换 (fast Fourier transform),即利用计算机计算离散傅里叶变换(DFT)的高效、快速计算方法的统称,简称FFT。快速傅里叶变换是1965年由J.W.库利和T.W.图基提出的。采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少&…

第四章快速傅里叶变换FFT

一、基2FFT算法 1.直接计算DFT的特点 对于N点DFT的乘法和加法运算次数均为N^2(运算量较大)减少运算量的基本途径:将N点DFT分解成多个较短的DFT旋转因子具有 周期性: 对称性:或又或者 2.时域抽取法基2FFT基本原理 分类:基2FFT分…

数学专题小结:FFT算法

快速傅里叶变换(FFT,Fast Fourier Transform)是信号处理的常用手段,可以把时域信号变成频域信号,时域的卷积运算对应于频域就成了简单的乘法运算。由于两个多项式的乘积,其系数的运算实际上也是一种卷积运算,因此可以用FFT来计算多项式的乘法。网上关于FFT算法的讲解大多…

转:fft算法(快速傅里叶变换算法)

FFT (Fast Fourier Transform) 是一种快速傅里叶变换算法。它是用来将一个信号从时域转换到频域的算法。这个算法通过分治策略,将一个长度为 N 的复数序列分解成 N/2 个长度为 2 的复数序列,然后对这些小的序列分别进行 FFT 计算。 最简单的 FFT 算法是暴…

快速傅里叶变换(FFT)算法学习

前言 人生如逆旅,我亦是行人。 一、介绍 算法的世界多么广大,我们可以将算法大致分为两类: 第一类是较为有用的算法:比如一些经典的图算法,像 DFS 和 BFS(深度 / 广度优先算法),这些…

FFT算法讲解——麻麻我终于会FFT了!

FFT——快速傅里叶变换 这块不写东西空荡荡的,我决定还是把FFT的定义给贴上吧 FFT(Fast Fourier Transformation)是离散傅氏变换(DFT)的快速算法。即为快速傅氏变换。它是根据离散傅氏变换的奇、偶、虚、实等特性&…