傅里叶和互相关算法及c程序解析
傅里叶变换c程序

傅里叶变换c程序傅里叶变换是一种用于分析和处理信号的重要数学工具,广泛应用于信号处理、图像处理、通信系统等领域。
在数学上,傅里叶变换可以将一个时域上的连续或离散信号转换为频域上的连续或离散信号,从而提供了一种将信号从时域转换为频域表示的方法。
在计算机科学中,傅里叶变换也有很大的应用。
通过使用傅里叶变换算法,可以对信号进行频谱分析,提取信号的频率成分,并在频域上进行滤波、去噪等处理。
傅里叶变换的计算可以使用多种方法,包括连续傅里叶变换(FFT)和离散傅里叶变换(DFT)。
为了实现傅里叶变换的计算,可以使用C语言编写相应的程序。
下面是一个简单的傅里叶变换C程序的示例:```c#include <stdio.h>#include <stdlib.h>#include <math.h>#define PI 3.14159265typedef struct {double real;double imag;} Complex;void fft(Complex* x, int N) {if (N <= 1) {}Complex* even = (Complex*) malloc(N/2 * sizeof(Complex)); Complex* odd = (Complex*) malloc(N/2 * sizeof(Complex)); for (int i = 0; i < N/2; i++) {even[i] = x[2*i];odd[i] = x[2*i + 1];}fft(even, N/2);fft(odd, N/2);for (int k = 0; k < N/2; k++) {Complex t;double angle = -2 * PI * k / N;t.real = cos(angle) * odd[k].real + sin(angle) * odd[k].imag; t.imag = cos(angle) * odd[k].imag - sin(angle) * odd[k].real; x[k].real = even[k].real + t.real;x[k].imag = even[k].imag + t.imag;x[k + N/2].real = even[k].real - t.real;x[k + N/2].imag = even[k].imag - t.imag;}free(even);}int main(void) {int N = 8;Complex* x = (Complex*) malloc(N * sizeof(Complex));// 初始化输入信号for (int i = 0; i < N; i++) {x[i].real = i;x[i].imag = 0;}fft(x, N);printf("傅里叶变换结果:\n");for (int i = 0; i < N; i++) {printf("X[%d] = %.2f + %.2fi\n", i, x[i].real, x[i].imag);}free(x);return 0;}```该程序演示了如何通过C代码实现傅里叶变换。
傅里叶在c语言中的使用

傅里叶在c语言中的使用傅里叶变换是一种在信号处理、图像处理等领域具有重要应用的算法。
它可以帮助我们将复杂的信号分解成一系列简单的正弦和余弦函数的叠加,从而更好地分析信号的频率特性。
在C语言中,傅里叶变换有着广泛的应用,下面我们将介绍傅里叶变换的基本概念、实现方法以及应用场景。
一、傅里叶变换的基本概念傅里叶变换是一种将时间域或空间域的信号转换为频域信号的数学方法。
其基本原理是将一个复杂的信号分解成无数个简单的正弦和余弦函数的叠加,这种叠加称为傅里叶级数。
在实际应用中,为了减少计算量,通常只取级数的前几项进行计算。
傅里叶变换的数学表达式如下:X(f) = ∫(-∞,∞) x(t) * e^(-jωt) dt其中,x(t)表示时域信号,X(f)表示频域信号,ω表示角频率,j表示虚数单位。
二、傅里叶变换在C语言中的实现方法1.离散傅里叶变换(DFT)离散傅里叶变换是傅里叶变换的一种离散形式,适用于离散信号的处理。
在C语言中,可以使用以下步骤实现DFT:(1)预处理:对输入信号进行窗函数处理,以减少频谱泄漏和旁瓣干扰。
(2)计算:按照DFT的计算公式,对输入信号的每个样本进行傅里叶变换。
(3)后处理:对变换结果进行幅度谱和相位谱的计算,并进行归一化处理。
2.快速傅里叶变换(FFT)快速傅里叶变换是一种高效计算离散傅里叶变换的方法,其时间复杂度为O(n log n)。
在C语言中,可以使用以下步骤实现FFT:(1)初始化:根据输入信号的长度,构建FFT递归函数。
(2)基2递归:按照FFT递归函数,对输入信号进行分组,并计算每组的傅里叶变换结果。
(3)合并:将每组的傅里叶变换结果合并,得到最终的傅里叶变换结果。
三、傅里叶变换的应用场景傅里叶变换在信号处理、图像处理等领域具有广泛的应用,如音频信号分析、图像滤波、模式识别等。
通过傅里叶变换,我们可以更好地分析信号的频率特性,从而为后续的处理和分析提供便利。
四、C语言实现傅里叶变换的实战案例以下是一个简单的C语言实现离散傅里叶变换的示例:```c#include <stdio.h>#include <stdlib.h>#include <math.h>void fft(float *in, float *out, int n) {// 基2递归实现FFT}int main() {int n = 8; // 采样点数float x[] = {1, 1, 1, 0, 0, 0, 0, 0}; // 输入信号float x_fft[n]; // 傅里叶变换结果fft(x, x_fft, n);// 输出傅里叶变换结果for (int i = 0; i < n; i++) {printf("x[%d] = %f", i, x_fft[i]);}return 0;}```五、总结与展望本文介绍了傅里叶变换在C语言中的基本概念、实现方法和应用场景。
傅里叶变换的应用,matlab程序,C语言程序

傅里叶变换的应用,m a t l a b 程序,C语言程序(总17页)本页仅作为文档封面,使用时可以删除This document is for reference only-rar21year.March1 利用FFT 计算连续时间信号的傅里叶变换设()x t 是连续时间信号,并假设0t <时()0x t =,则其傅里叶变换由下式给出()()i t X x t e dt ωω∞-=⎰令Γ是一个固定的正实数,N 是一个固定的正整数。
当,0,1,2,,1k k N ω=Γ=-时,利用FFT 算法可计算()X ω。
已知一个固定的时间间隔T ,选择T 足够小,使得每一个T 秒的间隔(1)nT t n T ≤<+内,()x t 的变化很小,则式中积分可近似为(1)0()()()n Tiwt nTn X e dt x nT ω∞+-==∑⎰(1)01[]()i t t n Tt nT n e x nT i ωω∞-=+==-=∑ 01()i Ti nTn e ex nT i ωωω-∞-=-=∑ (27)假设N 足够大,对于所有n N ≥的整数,幅值()x nT 很小,则式(27)变为11()()i TN i nTn e X ex nT i ωωωω---=-=∑ (28)当2/k NT ωπ=时,式(28)两边的值为2/2/12/0211()()[]2/2/i k Ni k NN i nk Nn k e e X ex nT X k NT i k NTi k NTππππππ----=--==∑ (29)其中[]X k 代表抽样信号[]()x n x nT =的N 点DFT 。
最后令2/NT πΓ=,则上式变为2/1()[]0,1,2,,12/i k Ne X k X k k N i k NTππ--Γ==- (30)首先用FFT 算法求出[]X k ,然后可用上式求出0,1,2,,1k N =-时的()X k Γ。
快速傅里叶变换FFT的C程序代码实现

快速傅⾥叶变换FFT的C程序代码实现标签:傅⾥叶变换(27)C程序(60) ⼀、彻底理解傅⾥叶变换 快速傅⾥叶变换(Fast Fourier Transform)是离散傅⾥叶变换的⼀种快速算法,简称FFT,通过FFT可以将⼀个信号从时域变换到频域。
模拟信号经过A/D转换变为数字信号的过程称为采样。
为保证采样后信号的频谱形状不失真,采样频率必须⼤于信号中最⾼频率成分的2倍,这称之为采样定理。
假设采样频率为fs,采样点数为N,那么FFT结果就是⼀个N点的复数,每⼀个点就对应着⼀个频率点,某⼀点n(n从1开始)表⽰的频率为:fn=(n-1)*fs/N。
举例说明:⽤1kHz的采样频率采样128点,则FFT结果的128个数据即对应的频率点分别是0,1k/128,2k/128,3k/128,…,127k/128 Hz。
这个频率点的幅值为:该点复数的模值除以N/2(n=1时是直流分量,其幅值是该点的模值除以N)。
⼆、傅⾥叶变换的C语⾔编程 1、对于快速傅⾥叶变换FFT,第⼀个要解决的问题就是码位倒序。
假设⼀个N点的输⼊序列,那么它的序号⼆进制数位数就是t=log2N. 码位倒序要解决两个问题:①将t位⼆进制数倒序;②将倒序后的两个存储单元进⾏交换。
如果输⼊序列的⾃然顺序号i⽤⼆进制数表⽰,例如若最⼤序号为15,即⽤4位就可表⽰n3n2n1n0,则其倒序后j对应的⼆进制数就是n0n1n2n3,那么怎样才能实现倒序呢?利⽤C语⾔的移位功能! 程序如下,我不多说,看不懂者智商⼀定在180以下! 复数类型定义及其运算 #define N 64 //64点 #define log2N 6 //log2N=6 /*复数类型*/ typedef struct { float real; float img; }complex; complex xdata x[N]; //输⼊序列 /*复数加法*/ complex add(complex a,complex b) { complex c; c.real=a.real+b.real; c.img=a.img+b.img; return c; } /*复数减法*/ complex sub(complex a,complex b) { complex c; c.real=a.real-b.real; c.img=a.img-b.img; return c; } /*复数乘法*/ complex mul(complex a,complex b) { complex c; c.real=a.real*b.real - a.img*b.img; c.img=a.real*b.img + a.img*b.real; return c; } /***码位倒序函数***/ void Reverse(void) { unsigned int i,j,k; unsigned int t; complex temp;//临时交换变量 for(i=0;i<N;i++)//从第0个序号到第N-1个序号 { k=i;//当前第i个序号 j=0;//存储倒序后的序号,先初始化为0 for(t=0;t<log2N;t++)//共移位t次,其中log2N是事先宏定义算好的 { j<<=1; j|=(k&1);//j左移⼀位然后加上k的最低位 k>>=1;//k右移⼀位,次低位变为最低位 } if(j>i)//如果倒序后⼤于原序数,就将两个存储单元进⾏交换(判断j>i是为了防⽌重复交换) { temp=x; x=x[j]; x[j]=temp; } } } 2、第⼆个要解决的问题就是蝶形运算 ①第1级(第1列)每个蝶形的两节点“距离”为1,第2级每个蝶形的两节点“距离”为2,第3级每个蝶形的两节点“距离”为4,第4级每个蝶形的两节点“距离”为8。
傅里叶变换物理意义及C语言实现

傅里叶变换的物理意义及C语言实现1.傅里叶变换的背景1807年,39岁的法国数学家傅里叶于法国科学学会上展示了一篇论文(此时不能算发表,该论文要到21年之后发表),论文中有个在当时极具争议的论断:“任何连续周期信号可以由一组适当的正弦曲线组合而成”。
傅里叶正反变换公式如下:这篇论文,引起了法国另外两位著名数学家拉普拉斯和拉格朗日的极度关注!58岁的拉普拉斯赞成傅里叶的观点,71岁的拉格朗日则反对,反对的理由是“正弦曲线无法组合成一个带有棱角的信号”。
屈服于朗格朗日的威望,该论文直到朗格朗日去世后的第15年才得以发表。
之后的科学家证明:傅里叶和拉格朗日都是对的!有限数量的正弦曲线的确无法组合成一个带有棱角的信号。
然而,无限数量的正弦曲线的组合从能量的角度可以非常无限逼近带有棱角的号。
2.傅里叶变换的物理意义傅里叶的伟大之处不在于如何进行傅里叶变换,而是在于给出了“任何连续周期信号可以由一组适当的正弦曲线组合而成”这一伟大的论断。
知道了这一论断,只要知道正弦函数的基本特性,变换并不难,不需要记公式,也能实规傅里叶变换!正弦函数有一个特点,叫做正交性,所谓正交性,是指任意两个不同频率的正弦波的乘积,在两者的公共周期内的积分等于零。
这是一个非常有用的特性,我们可以利用这个特性设计一个如下的检波器A用来检测某频率的sin信号分量图1-1检测某频率的sin信号分量检波器A由一个乘法器和一个积分器构成,乘法器的一个输入为已知频率f的单位幅值正弦波(下称标准正弦信号f),另一个输入为待变换的信号。
检波器A的输出只与待变换信号中的频率为f的正弦分量的幅值和相位有关。
待变换信号可能包含频率为f的分量(下称f分量),也可能不包含f分量,总之,可能包含各种频率分量。
一句话,待变换信号是未知的,并且可能很复杂!没关系,我们先看看,待变换信号是否包含f分量。
因为其它频率分量与标准正弦信号f的乘积的积分都等于零,检波器A可以当它们不存在!经过检波器A,输出就只剩下与f分量有关的一个量,这个量等于待变换信号中f分量与标准正弦信号f的乘积的积分。
傅里叶变换及C语言实现

傅里叶变换及C语言实现傅里叶变换(Fourier Transform)是一种将时域信号转换为频域信号的数学工具。
它是由法国数学家傅里叶(Joseph Fourier)在19世纪提出的,被广泛应用于信号处理、图像处理、通信等领域。
F(k)=∫[f(x)e^(-2πikx)]dx其中,F(k)是频域中的复数值表示,k表示频率,f(x)是时域信号。
在计算机中,我们通常使用离散傅里叶变换(Discrete Fourier Transform,简称DFT),用于处理离散的时域信号。
离散傅里叶变换可以表示为:X(k)=∑[x(n)e^(-2πikn/N)]其中,X(k)是频域中的复数值表示,k表示频率,x(n)是时域信号,N表示信号的长度。
C语言是一种广泛应用于嵌入式系统、操作系统、驱动程序等领域的编程语言。
在C语言中,我们可以通过编写代码来实现傅里叶变换。
以下是一个简单的C语言程序,用于实现离散傅里叶变换(DFT):```C#include <stdio.h>#include <math.h>#define N 8 // 信号长度typedef structdouble real;double imag;int k, n;double angle;for(k = 0; k < N; k++)output[k].real = 0;output[k].imag = 0;for(n = 0; n < N; n++)angle = 2 * M_PI * k * n / N;output[k].real += input[n].real * cos(angle) + input[n].imag * sin(angle);output[k].imag += input[n].imag * cos(angle) - input[n].real * sin(angle);}}int main(void)int k;dft(input, output);for(k = 0; k < N; k++)printf("X(%d) = %f + %fi\n", k, output[k].real,output[k].imag);}return 0;```该程序中的信号长度N为8,可以根据实际需求进行修改。
傅里叶变换c代码 -回复

傅里叶变换c代码-回复题目:傅里叶变换C语言代码及其应用引言:傅里叶变换是一种重要的数学工具,常用于信号处理、图像处理等领域。
该算法可以将一个时域(时长域)上的信号转换成频域(频率域)上的信号,实现信号的频谱分析和滤波处理。
本文将详细介绍傅里叶变换的原理,并提供一段C语言代码实现傅里叶变换,同时探讨其应用。
一、傅里叶变换的基本原理在傅里叶变换中,信号通常被表示为周期信号,由无穷多个正弦和余弦函数的和构成。
傅里叶变换可以将一个信号从时域(t-domain)表示转换为频域(f-domain)表示,即从时延-幅度表示转变为频率-幅度表示。
傅里叶变换的公式如下所示:F(k) = ∫f(t) * exp(-2 * π* i * k * t) dt其中,F(k)表示频域上的值,f(t)表示时域上的值,k为频率。
二、傅里叶变换C代码实现下面的C语言代码演示了如何实现傅里叶变换:#include <stdio.h>#include <math.h>#include <complex.h>#define PI 3.14159265void fft(double complex *input, double complex *output, int n) { if (n == 1) {output[0] = input[0];return;}double complex even[n / 2], odd[n / 2];for (int i = 0; i < n / 2; i++) {even[i] = input[2 * i];odd[i] = input[2 * i + 1];}double complex even_result[n / 2], odd_result[n / 2];fft(even, even_result, n / 2);fft(odd, odd_result, n / 2);for (int i = 0; i < n / 2; i++) {double complex t = cexp(-2 * PI * i / n * I) * odd_result[i];output[i] = even_result[i] + t;output[i + n / 2] = even_result[i] - t;}}int main() {int n = 8;double complex input[n], output[n];输入信号printf("输入信号:\n");for (int i = 0; i < n; i++) {input[i] = i + 1;printf(".2lf + .2lfi\n", creal(input[i]), cimag(input[i]));}执行傅里叶变换fft(input, output, n);输出频域信号printf("\n频域信号:\n");for (int i = 0; i < n; i++) {printf(".2lf + .2lfi\n", creal(output[i]), cimag(output[i]));}return 0;}以上代码实现了一个简单的递归快速傅里叶变换(FFT)算法。
傅里叶和互相关算法及c程序

1.快速傅里叶变换(FFT )1.1 叶变换简介快速傅里有限长序列可以通过离散傅里叶变换(DFT)将其频域也离散化成有限长序列.但其计算量太大,很难实时地处理问题,因此引出了快速傅里叶变换(FFT). 1965 年,Cooley 和Tukey 提出了计算离散傅里叶变换(DFT )的快速算法,将DFT 的运算量减少了几个数量级。
从此,对快速傅里叶变换( FFT )算法的研究便不断深入,数字信号处理这门新兴学科也随FFT 的出现和发展而迅速发展。
根据对序列分解与选取方法的不同而产生了FFT 的多种算法,基本算法是基-2DIT 和基-2DIF 。
FFT 在离散傅里叶反变换、线性卷积和线性相关等方面也有重要应用。
快速傅氏变换(FFT ),是离散傅氏变换的快速算法,它是根据离散傅氏变换的 奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。
它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。
快速傅立叶变换作为一种数学方法,已经广泛地应用在几乎所有领域的频谱分析中,而且经久不衰,因为信号处理方法没有先进和落后之分,只有经典和现代之别,在实际系统中用得最好的方法就是管用的方法。
换句话说,信号处理方法与应用背景和目的的贴近程度是衡量信号处理方法优劣的唯一标准。
FFT 是快速傅利叶变换(Fast FourierTransform 简称FFT)的英文缩写,它在当今科技世界中的应用相当活跃,无论是在时间序列分析领域中,还是在我国刚刚兴起的生物频谱治疗的研究与应用中,都有着重要的作用。
同时,它又是软件实现数字滤波器的必备组成部分之一。
FFT 算法的基本思想:利用DFT 系数的特性,合并DFT 运算中的某些项,把长序列的DFT —>短序列的DFT ,从而减少其运算量。
FFT 算法分类: 时间抽选法DIT: Decimation-In-Time ; 频率抽选法DIF: Decimation-In-Frequency 。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.快速傅里叶变换(FFT )1.1 叶变换简介快速傅里有限长序列可以通过离散傅里叶变换(DFT)将其频域也离散化成有限长序列.但其计算量太大,很难实时地处理问题,因此引出了快速傅里叶变换(FFT). 1965 年,Cooley 和Tukey 提出了计算离散傅里叶变换(DFT )的快速算法,将DFT 的运算量减少了几个数量级。
从此,对快速傅里叶变换( FFT )算法的研究便不断深入,数字信号处理这门新兴学科也随FFT 的出现和发展而迅速发展。
根据对序列分解与选取方法的不同而产生了FFT 的多种算法,基本算法是基-2DIT 和基-2DIF 。
FFT 在离散傅里叶反变换、线性卷积和线性相关等方面也有重要应用。
快速傅氏变换(FFT ),是离散傅氏变换的快速算法,它是根据离散傅氏变换的 奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。
它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。
快速傅立叶变换作为一种数学方法,已经广泛地应用在几乎所有领域的频谱分析中,而且经久不衰,因为信号处理方法没有先进和落后之分,只有经典和现代之别,在实际系统中用得最好的方法就是管用的方法。
换句话说,信号处理方法与应用背景和目的的贴近程度是衡量信号处理方法优劣的唯一标准。
FFT 是快速傅利叶变换(Fast FourierTransform 简称FFT)的英文缩写,它在当今科技世界中的应用相当活跃,无论是在时间序列分析领域中,还是在我国刚刚兴起的生物频谱治疗的研究与应用中,都有着重要的作用。
同时,它又是软件实现数字滤波器的必备组成部分之一。
FFT 算法的基本思想:利用DFT 系数的特性,合并DFT 运算中的某些项,把长序列的DFT —>短序列的DFT ,从而减少其运算量。
FFT 算法分类: 时间抽选法DIT: Decimation-In-Time ; 频率抽选法DIF: Decimation-In-Frequency 。
在此以按时间抽选的基-2FFT 算法为例进行说明。
1.2 算法原理N 为2 的整数幂的FFT 算法称基-2FFT 算法。
设N 点序列()x n ,n =0,1,2,…N-1 按n 的奇偶分成两个长为N/2的序列12()(2)()(21)x r x r x r x r ==+ r =0,1,2,…,2N-1由于2/2N N W W =则()x n 的DFT :111()()()()N N N nk nk nkNNN n n n X k x n Wx n Wx n W ---=====+∑∑∑ n 为偶数 n 为奇数 =11222(21)0(2)(21)NN rk r kNN r r x r Wx r W --+==++∑∑ =11221/22/20()()N Nrk k rk N N N r r x r WW x r W --==+∑∑=12()()kN X k W X k + k =0,1,2,…,N-1 (1) 其中:1()X k =12/20(2)N rk Nr x r W -=∑=121/20()N rkN r x r W -=∑ (2)2()X k =12/20(21)N rk Nr x r W -=+∑=122/20()N rkN r x r W -=∑ (3)按式(1)计算得到的只是()X k 的前一半项数的结果,即(0≤k ≤2N —1)。
由系数的周期性可推出()X k 的后一半值,即(2N ≤k ≤N —1):. (/2)/2/2r k N rk N N W W += (/2)/2k N k N k NN N N W W W W +=⋅=- (/2N N W =—1) 又因为1()X k ,2()X k 是以2N 为周期的,可推出: 1122(/2)11/21/210(/2)()()()NN r k N rkN N r r X k N x r W x r W X k --+==+===∑∑ (4)同理可得,2(/2)X k N +=2()X k (5) 由此可得N 点对应的DFT ()X k 的计算式子:1212()()()(/2)()()kN kNX k X k W X k X k N X k W X k =++=- k =0,1,2,…,2N -1 (6)上一式计算()X k 的前一半值,下一式计算()X k 的后一半值。
因此只要求出0~2N —1区间内各个整数k 值所对应的1()X k 和2()X k ,便可求出0到N-1点全部的()X k 值。
明显节约了运算量。
式中因子k N W 在复数乘法中起一个旋转的作用,称为旋转因子。
公式(6)的运算可以归结为两个复数a 、b 求得复数k N a bW +和k N a bW -。
用信号流程图的方法可以简单的表示为如图2所示。
这样的运算称为蝶形运算,在FFT 算法中占有核心的地位。
图2 时间抽选蝶形运算流图显然,每个蝶形运算对应于一次复数乘法和两次复数加法运算。
如果用DFT方法直接计算出1()X k 和2()X k ,共需22N 次复数乘法运算,再作N/2次蝶形运算,又需N/2次复数乘法和N 次复数加法。
这样算出N 点DFT 共需要(2N +N )/2次复数乘法和(2N /2)+N 次复数加法。
当N 较大时,同直接计算N 点DFT 所需的2N 次复数乘加次数相比,几乎减少了一半的计算量。
假设N/2还是偶数,则1()X k 和2()X k 这两个N/2点的DTF 计算,又分别可以通过计算N/4点DFT 和蝶形运算而得到。
这时蝶形有两组,每组N/4个,总数也是N/2个,所以也需要N/2次复数乘法和N 次复数加法。
如果N=2M ,则分解过程一直可以进行下去,共分解M 次,到2点DFT 为止。
以上所述就是FFT 算法的核心思想。
可以看出,这种罪基本形式的快速傅里叶算法要求点数是2的幂次。
当序列长度不具有2M 的形式时,可以补上一段0,使总长度为2M 。
1.3时间抽取过程的流图表示现在就N=8的情况对算法结构,即计算流图作详细的说明,由此可以直接得到关于N=2M 的情况下得一些一般性结论。
图3是8点DFT 欧诺个两个4点DFT 和4个蝶形运算实现的图示,图4中进一步将4点DFT 作类似的分解,最后将图4中的2点DFT 也画成蝶形运算流图,如图5所示。
整个运算有3轮蝶形运算构成,每一轮有4个蝶形,但它们的旋转因子和循环方式各轮有所不同。
()()12kN X k W X k +()()12k N X k W X k -()1X k ()2X k()0 x ()4x()2 x()6 x()1x ()5 x ()3 x ()7 x()2X()1X()0X()4X()3X()5X()6X()7X()0X()0x(4)xN(2)x(6)x(1)x(3)x(5)x(7)x()1X()2X()4X()3X()5X()6X()7X图48点DFT时间抽选分解(续)图5 反序输入顺序输出时间抽选FFT 算法流图图5那样的结构对任何N=2M 的序列都是适用的。
整个N 点DFT 的计算可用M=2log N 轮蝶形运算构成,每轮有N/2个蝶形,因此总的运算就由这12N 2log N 个蝶形所构成。
因此总的复数乘法次数是12N 2log N ,复数加法次数是N 2log N 。
1.4 运算量下面讨论按时间抽取法的运算量,对于任意一个N=2M 的DFT 运算,都可以通过M 次分解,最后分解成2点DFT 运算的组合。
这样的M 次分解,就构成由()x n 到()X k 的M 级运算过程,每一级运算都有N/2个蝶式运算完成。
而每一蝶式运算有一次复数乘法和两次复数加法。
因此,每一级运算都需要N/2次复数乘法和N 次复数加法。
这样M 级运算共需要复数乘法: 2(/2)(/2)log p m N M N N == 复数加法: 2log p a N M N N =⋅=为了比较FFT 算法与直接DFT 运算的运算量,现将二者在不同N 值时的乘法次数列于表1中,并将直接计算DFT 与FFT 算法的计算量之比22/(/2)log N N N 也列于表中。
从表中可以看出,当N 较大时,时间抽取法要比直接计算块一、二个()0x ()4x ()2x ()6x ()1x ()5x ()3x ()7x ()2X ()1X()0X ()4X ()3X ()5X ()6X ()7X数量级。
表1 FFT算法与直接计算DFT算法的比较1.5按时间抽取的FFT算法特点(1)原位运算(同址运算)由所述算法原理及图5的N=8的信号流图,FFT的每级(列)计算都是由N个复数据经N/2个蝶形运算变成了另外N个复数据。
每一个蝶形运算结构完成下述基本迭代运算11()()()km m m NA i A i A jW--=+(7)11()()()km m m NA j A i A j W--=-(8)式中m表示第m列迭代,i、j为数据所在的行数。
上式的运算如图6所示,由一次复数乘法和一次复数加减法组成。
任何两个节点i和j的节点变量进行蝶形运算后,其结果为下一列的i和j两点的节点变量,而和其他节点变量无关。
图6(2)输入序列的序号及整序规律由图5可见,当按原位进行计算时,FFT输出端的()X k的次序正好是顺序排列的。
但这时输入()x n却不能按自然顺序存入存储单元中,而是按(0)x,(4)x,(2)x,(6)x ,…的顺序存入存储单元,因而是乱序的。
这就使得运算时取数据的地址编排“混乱无序”。
但实际上是由规律可寻的,我们称为倒位序。
乱序的原因是由按时间抽取进行的FFT 运算的原理造成的,是由于输入()x n 按标号n 的奇偶不断分组造成的。
如果你用二进制数表示为2102()n n n (当N=8=32时,用三位二进制符号表示),第一次分组n 为偶数,在上半部分,n 为奇数在下半部分,这可以观察n 的二进制的最低位0n ,0n =0则序列值对应于偶数抽样,0n =1则序列值对应于奇数抽样。
下一次则根据次最低位1n 的0,1来分奇偶(而不管原来的序列的子序列是偶序列还是奇序列)。
在实际运算中,直接将输入数据()x n 按原位运算要求的“乱序”存放是很不方便的。
因此总是先按自然顺序将输入序列存入存储单元,再通过变址运算将自然顺序变换成按时间抽取的FFT 算法要求的顺序。
变址的过程可以用程序安排加以实现,称为“整序”或“重排”。
整序规律:如果输入序列的序号n 用二进制数表示,如210n n n ,若其反序二进制n∧用012n n n 来表示,则原来在自然顺序时应该放()x n 的存储单元,现在放着的是()x n ∧。
表2列出了N=8时的自然顺序二进制数以及相应的倒位序二进制数。