快速傅里叶算法C语言完整实现
C语言编写FFT程序
DSP 课程作业用C 语言编写FFT 程序1,快速傅里叶变换FFT 简介快速傅氏变换(FFT ),是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。
它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。
我们假设 x(n)为N 项的复数序列,由DFT 变换,任一X (m )的计算都需要N 次复数乘法和N-1次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法,即使把一次复数乘法和一次复数加法定义成一次“运算”(四次实数乘法和四次实数加法),那么求出N 项复数序列的X (m ),即N 点DFT 变换大约就需要N^2次运算。
当N=1024点甚至更多的时候,需要N2=1048576次运算,在FFT 中,利用WN 的周期性和对称性,把一个N 项序列(设N=2k,k 为正整数),分为两个N/2项的子序列,每个N/2点DFT 变换需要(N/2)2次运算,再用N 次运算把两个N/2点的DFT 变换组合成一个N 点的DFT 变换。
这样变换以后,总的运算次数就变成N+2(N/2)2=N+N2/2。
继续上面的例子,N=1024时,总的运算次数就变成了525312次,节省了大约50%的运算量。
而如果我们将这种“一分为二”的思想不断进行下去,直到分成两两一组的DFT 运算单元,那么N 点的DFT 变换就只需要Nlog2N 次的运算,N 在1024点时,运算量仅有10240次,是先前的直接算法的1%,点数越多,运算量的节约就越大,这就是FFT 的优越性。
2,FFT 算法的基本原理FFT 算法的基本思想:利用DFT 系数的特性,合并DFT 运算中的某些项,吧长序列的DFT —>短序列的DFT ,从而减少其运算量。
FFT 算法分类:时间抽选法DIT: Decimation-In-Time ;频率抽选法DIF: Decimation-In-Frequency按时间抽选的基-2FFT 算法1、算法原理设序列点数 N = 2L ,L 为整数。
C语言编写FFT程序
DSP 课程作业用C 语言编写FFT 程序1,快速傅里叶变换FFT 简介快速傅氏变换(FFT ),是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。
它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。
我们假设 x(n)为N 项的复数序列,由DFT 变换,任一X (m )的计算都需要N 次复数乘法和N-1次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法,即使把一次复数乘法和一次复数加法定义成一次“运算”(四次实数乘法和四次实数加法),那么求出N 项复数序列的X (m ),即N 点DFT 变换大约就需要N^2次运算。
当N=1024点甚至更多的时候,需要N2=1048576次运算,在FFT 中,利用WN 的周期性和对称性,把一个N 项序列(设N=2k,k 为正整数),分为两个N/2项的子序列,每个N/2点DFT 变换需要(N/2)2次运算,再用N 次运算把两个N/2点的DFT 变换组合成一个N 点的DFT 变换。
这样变换以后,总的运算次数就变成N+2(N/2)2=N+N2/2。
继续上面的例子,N=1024时,总的运算次数就变成了525312次,节省了大约50%的运算量。
而如果我们将这种“一分为二”的思想不断进行下去,直到分成两两一组的DFT 运算单元,那么N 点的DFT 变换就只需要Nlog2N 次的运算,N 在1024点时,运算量仅有10240次,是先前的直接算法的1%,点数越多,运算量的节约就越大,这就是FFT 的优越性。
2,FFT 算法的基本原理FFT 算法的基本思想:利用DFT 系数的特性,合并DFT 运算中的某些项,吧长序列的DFT —>短序列的DFT ,从而减少其运算量。
FFT 算法分类:时间抽选法DIT: Decimation-In-Time ;频率抽选法DIF: Decimation-In-Frequency按时间抽选的基-2FFT 算法1、算法原理设序列点数 N = 2L ,L 为整数。
编程实现快速傅里叶变换(fft)
一、概述傅里叶变换是信号处理和数据压缩中常用的数学工具,它可以将时域信号转换为频域信号,从而便于分析和处理。
而快速傅里叶变换(FFT)则是一种高效的计算傅里叶变换的方法,可以大大提高计算效率,广泛应用于信号处理、图像处理、通信系统等领域。
二、傅里叶变换原理傅里叶变换的基本思想是将一个时域信号分解为不同频率的正弦和余弦函数的叠加,从而得到该信号的频谱图。
具体来说,对于一个连续信号x(t),它的傅里叶变换X(ω)定义为:X(ω) = ∫[0,∞]x(t)e^(-jωt)dt其中,ω为频率变量,X(ω)表示在频率ω处的信号能量。
而对于离散信号x[n],它的傅里叶变换X[k]则定义为:X[k] = ∑[n=0,N-1]x[n]e^(-j2πkn/N)其中,N为信号的采样点数,k为频率域的序号。
上述公式称为离散傅里叶变换(DFT),计算复杂度为O(N^2)。
而快速傅里叶变换则通过巧妙的算法设计,将计算复杂度降低到O(NlogN)。
三、快速傅里叶变换算法概述快速傅里叶变换的算法最早由Cooley和Tukey在1965年提出,它的基本思想是将一个长度为N的DFT分解为两个长度为N/2的DFT的组合,通过递归地分解和合并,最终实现对整个信号的快速计算。
下面我们来介绍一种常用的快速傅里叶变换算法:递归式分治法。
四、递归式分治法递归式分治法是一种高效的计算DFT的方法,它的基本思想是将长度为N的DFT分解为两个长度为N/2的DFT,并通过递归地调用自身,最终实现对整个信号的傅里叶变换。
具体来说,假设有一个长度为N的信号x[n],对其进行快速傅里叶变换的过程可以分为如下几个步骤:1. 将长度为N的信号x[n]分为长度为N/2的偶数序号和奇数序号的两个子信号x_even[n]和x_odd[n];2. 对子信号x_even[n]和x_odd[n]分别进行快速傅里叶变换,得到它们的频域表示X_even[k]和X_odd[k];3. 结合X_even[k]和X_odd[k],计算原信号的频域表示X[k]。
C语言实现FFT(快速傅里叶变换)
#include <iom128.h>#include <intrinsics.h>/*********************************************************************快速福利叶变换C函数函数简介:此函数是通用的快速傅里叶变换C语言函数,移植性强,以下部分不依赖硬件。
此函数采用联合体的形式表示一个复数,输入为自然顺序的复数(输入实数是可令复数虚部为0),输出为经过FFT变换的自然顺序的复数使用说明:使用此函数只需更改宏定义FFT_N的值即可实现点数的改变,FFT_N的应该为2的N次方,不满足此条件时应在后面补0函数调用:FFT(s);时间:2010-2-20版本:Ver1.0参考文献:**********************************************************************/#include<math.h>#define PI 3.1415926535897932384626433832795028841971 //定义圆周率值#define FFT_N 128 //定义福利叶变换的点数struct compx {float real,imag;}; //定义一个复数结构struct compx s[FFT_N]; //FFT输入和输出:从S[1]开始存放,根据大小自己定义/*******************************************************************函数原型:struct compx EE(struct compx b1,struct compx b2)函数功能:对两个复数进行乘法运算输入参数:两个以联合体定义的复数a,b输出参数:a和b的乘积,以联合体的形式输出*******************************************************************/struct compx EE(struct compx a,struct compx b){struct compx c;c.real=a.real*b.real-a.imag*b.imag;c.imag=a.real*b.imag+a.imag*b.real;return(c);}/*****************************************************************函数原型:void FFT(struct compx *xin,int N)函数功能:对输入的复数组进行快速傅里叶变换(FFT)输入参数:*xin复数结构体组的首地址指针,struct型*****************************************************************/void FFT(struct compx *xin){int f,m,nv2,nm1,i,k,l,j=0;struct compx u,w,t;nv2=FFT_N/2; //变址运算,即把自然顺序变成倒位序,采用雷德算法nm1=FFT_N-1;for(i=0;i<nm1;i++){if(i<j) //如果i<j,即进行变址{t=xin[j];xin[j]=xin[i];xin[i]=t;}k=nv2; //求j的下一个倒位序while(k<=j) //如果k<=j,表示j的最高位为1{j=j-k; //把最高位变成0k=k/2; //k/2,比较次高位,依次类推,逐个比较,直到某个位为0 }j=j+k; //把0改为1}{int le,lei,ip; //FFT运算核,使用蝶形运算完成FFT运算f=FFT_N;for(l=1;(f=f/2)!=1;l++) //计算l的值,即计算蝶形级数;for(m=1;m<=l;m++) // 控制蝶形结级数{ //m表示第m级蝶形,l为蝶形级总数l=log(2)Nle=2<<(m-1); //le蝶形结距离,即第m级蝶形的蝶形结相距le点lei=le/2; //同一蝶形结中参加运算的两点的距离u.real=1.0; //u为蝶形结运算系数,初始值为1u.imag=0.0;w.real=cos(PI/lei); //w为系数商,即当前系数与前一个系数的商w.imag=-sin(PI/lei);for(j=0;j<=lei-1;j++) //控制计算不同种蝶形结,即计算系数不同的蝶形结{for(i=j;i<=FFT_N-1;i=i+le) //控制同一蝶形结运算,即计算系数相同蝶形结{ip=i+lei; //i,ip分别表示参加蝶形运算的两个节点t=EE(xin[ip],u); //蝶形运算,详见公式xin[ip].real=xin[i].real-t.real;xin[ip].imag=xin[i].imag-t.imag;xin[i].real=xin[i].real+t.real;xin[i].imag=xin[i].imag+t.imag;}u=EE(u,w); //改变系数,进行下一个蝶形运算}}}}/************************************************************函数原型:void main()函数功能:测试FFT变换,演示函数使用方法输入参数:无输出参数:无************************************************************/void main(){int i;for(i=0;i<FFT_N;i++) //给结构体赋值{s[i].real=sin(2*3.141592653589793*i/FFT_N); //实部为正弦波FFT_N点采样,赋值为1 s[i].imag=0; //虚部为0}FFT(s); //进行快速福利叶变换for(i=0;i<FFT_N;i++) //求变换后结果的模值,存入复数的实部部分s[i].real=sqrt(s[i].real*s[i].real+s[i].imag*s[i].imag);while(1);}#include <iom128.h>#include <intrinsics.h>/*********************************************************************快速福利叶变换C程序包函数简介:此程序包是通用的快速傅里叶变换C语言函数,移植性强,以下部分不依赖硬件。
FFT及IFFTC语言实现
FFT及IFFTC语言实现FFT(快速傅里叶变换)和IFFT(快速傅里叶逆变换)是傅里叶变换在计算机科学和信号处理中的高效实现方法。
它们广泛应用于图像处理、音频处理、通信系统等领域。
下面将详细介绍FFT和IFFT的C语言实现。
首先,让我们了解一下DFT(离散傅里叶变换)。
DFT将一个离散的时间域序列转换为离散的频域序列,其定义如下:其中,N表示序列的长度,x(n)是输入序列,X(k)是输出序列。
FFT是DFT的一种高效实现方法,它利用了序列的对称性质,将操作的复杂度从O(N^2)降低到O(NlogN)。
IFFT则是FFT的逆过程,可以将频域序列恢复为时间域序列。
以下是FFT的C语言实现代码:```c#include <stdio.h>#include <math.h>typedef structdouble real;double imag;result.real = a.real * b.real - a.imag * b.imag;result.imag = a.real * b.imag + a.imag * b.real;return result;result.real = a.real + b.real; result.imag = a.imag + b.imag; return result;result.real = a.real - b.real; result.imag = a.imag - b.imag; return result;if (N <= 1)return;}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++)x[k] = add(even[k], t);x[k + N / 2] = subtract(even[k], t); }//完整的IFFT实现代码略,与FFT相似int mai//输入序列x(n)int N = sizeof(x) / sizeof(x[0]);//调用FFTfft(x, N);//输出频域序列X(k)for (int k = 0; k < N; k++)printf("X(%d) = %.2f + %.2fi\n", k, x[k].real, x[k].imag);}//调用IFFT//...return 0;```IFFT的实现与FFT类似,只需将其中几处计算公式略作变换即可。
FFT-C快速傅里叶变换超级详细的原代码
快速傅立叶变换(FFT)的C++实现收藏标准的离散傅立叶DFT 变换形式如:y k=Σj=0n-1a jωn-kj = A (ωn-k).(ωn k为复数1 的第k 个n 次方根,且定义多项式A (x)=Σj=0n-1a j x j)而离散傅立叶逆变换IDFT (Inverse DFT)形式如:a j=(Σk=0n-1y kωn kj)/n .yk=Σj=0n-1 ajωn-kj = A (ωn-k).(ωnk 为复数1 的第k 个n 次方根,且定义多项式 A (x) = Σj=0n-1 ajxj )而离散傅立叶逆变换IDFT (Inverse DFT)形式如:aj=(Σk=0n-1 ykωnkj)/n .以下不同颜色内容为引用并加以修正:快速傅立叶变换(Fast Fourier Transform,FFT)是离散傅立叶变换(Discrete Fourier transform,DFT)的快速算法,它是根据离散傅立叶变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。
它对傅立叶变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。
设Xn 为N 项的复数序列,由DFT 变换,任一Xi 的计算都需要N 次复数乘法和N -1 次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法,即使把一次复数乘法和一次复数加法定义成一次“运算”(四次实数乘法和四次实数加法),那么求出N 项复数序列的Xi ,即N 点DFT 变换大约就需要N2 次运算。
当N =1024 点甚至更多的时候,需要N2 = 1048576 次运算,在FFT 中,利用ωn 的周期性和对称性,把一个N 项序列(设N 为偶数),分为两个N / 2 项的子序列,每个N / 2点DFT 变换需要(N / 2)2 次运算,再用N 次运算把两个N / 2点的DFT 变换组合成一个N 点的DFT 变换。
(快速傅里叶变换)C语言程序
{
structpxc;
c。real=a。real*b。real-a。imag*b.imag;
c、imag=a.real*b.imag+a。imag*b、real;
return(c);
}
/*****************************************************************
#include 〈iom128.h>
#include〈intrinsics。h〉
/*********************************************************************
快速傅立叶变换C函数
函数简介:此函数就是通用得快速傅里叶变换C语言函数,移植性强,以下部分不依
函数原型:voidcos_tab(float pi)
函数功能:采用查表得方法计算一个数得余弦值
输入参数:pi所要计算余弦值弧度值,范围0--2*PI,不满足时需要转换
输出参数:输入值pi得余弦值
******************************************************************/
{
ip=i+lei;//i,ip分别表示参加蝶形运算得两个节点
t=EE(xin[ip],u);//蝶形运算,详见公式
xin[ip]、real=xin[i]。real-t。real;
xin[ip].imag=xin[i].imag-t.imag;
xin[i]、real=xin[i]。real+t。real;
C语言编写FFT程序
DSP 课程作业用C 语言编写FFT 程序1,快速傅里叶变换FFT 简介快速傅氏变换(FFT ),是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。
它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。
我们假设 x(n)为N 项的复数序列,由DFT 变换,任一X (m )的计算都需要N 次复数乘法和N-1次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法,即使把一次复数乘法和一次复数加法定义成一次“运算”(四次实数乘法和四次实数加法),那么求出N 项复数序列的X (m ),即N 点DFT 变换大约就需要N^2次运算。
当N=1024点甚至更多的时候,需要N2=1048576次运算,在FFT 中,利用WN 的周期性和对称性,把一个N 项序列(设N=2k,k 为正整数),分为两个N/2项的子序列,每个N/2点DFT 变换需要(N/2)2次运算,再用N 次运算把两个N/2点的DFT 变换组合成一个N 点的DFT 变换。
这样变换以后,总的运算次数就变成N+2(N/2)2=N+N2/2。
继续上面的例子,N=1024时,总的运算次数就变成了525312次,节省了大约50%的运算量。
而如果我们将这种“一分为二”的思想不断进行下去,直到分成两两一组的DFT 运算单元,那么N 点的DFT 变换就只需要Nlog2N 次的运算,N 在1024点时,运算量仅有10240次,是先前的直接算法的1%,点数越多,运算量的节约就越大,这就是FFT 的优越性。
2,FFT 算法的基本原理FFT 算法的基本思想:利用DFT 系数的特性,合并DFT 运算中的某些项,吧长序列的DFT —>短序列的DFT ,从而减少其运算量。
FFT 算法分类:时间抽选法DIT: Decimation-In-Time ;频率抽选法DIF: Decimation-In-Frequency按时间抽选的基-2FFT 算法1、算法原理设序列点数 N = 2L ,L 为整数。
快速傅里叶变换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语言实现FFT变换
C语言实现FFT变换FFT(快速傅里叶变换)是一种高效的算法,用于将时域信号转换为频域信号。
在C语言中,可以使用以下步骤实现FFT变换。
1.首先,需要定义复数结构体,用于表示实部和虚部。
```ctypedef structdouble real;double imag;```2.实现一个函数来进行复数的乘法操作。
```cresult.real = a.real * b.real - a.imag * b.imag;result.imag = a.real * b.imag + a.imag * b.real;return result;```3.编写一个函数来执行FFT变换。
```c//基线条件if (n == 1)return;}//分解信号for (int i = 0; i < n / 2; i++) even[i] = x[2 * i];odd[i] = x[2 * i + 1];}//递归计算FFTfft(even, n / 2, is_inverse);fft(odd, n / 2, is_inverse);//合并结果double angle = 2 * PI / n;if (is_inverse)angle = -angle;}for (int k = 0; k < n / 2; k++)x[k] = add(even[k], t);x[k + n / 2] = subtract(even[k], t); w = multiply(w, wn);}//释放内存free(even);free(odd);```4.编写一个函数来计算FFT结果的模值。
```cdouble* magnitude = (double*)malloc(n * sizeof(double));for (int i = 0; i < n; i++)magnitude[i] = sqrt(x[i].real * x[i].real + x[i].imag * x[i].imag);}return magnitude;```5.在主函数中使用上述函数进行FFT变换。
快速傅里叶变换FFT的C语言实现及应用
快速傅里叶变换FFT的C语言实现及应用快速傅里叶变换简介计算离散傅里叶变换的一种快速算法,简称FFT。
快速傅里叶变换是1965年由J.W.库利和T.W.图基提出的。
采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少,特别是被变换的抽样点数N越多,FFT算法计算量的节省就越显著。
有限长序列可以通过离散傅里叶变换(DFT)将其频域也离散化快速傅里叶变换成有限长序列.但其计算量太大,很难实时地处理问题,因此引出了快速傅里叶变换(FFT). 1965年,Cooley和Tukey提出了计算离散傅里叶变换(DFT)的快速算法,将DFT的运算量减少了几个数量级。
从此,对快速傅里叶变换(FFT)算法的研究便不断深入,数字信号处理这门新兴学科也随FFT的出现和发展而迅速发展。
根据对序列分解与选取方法的不同而产生了FFT的多种算法,基本算法是基2DIT和基2DIF。
FFT在离散傅里叶反变换、线性卷积和线性相关等方面也有重要应用。
快速傅氏变换(FFT),是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。
它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。
设快速傅里叶变换x(n)为N项的复数序列,由DFT变换,任一X(m)的计算都需要N次复数乘法和N-1次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实快速傅里叶变换数加法,即使把一次复数乘法和一次复数加法定义成一次“运算”(四次实数乘法和四次实数加法),那么求出N 项复数序列的X (m ),即N 点DFT 变换大约就需要N^2次运算。
当N=1024点甚至更多的时候,需要N2=1048576次运算,在FFT 中,利用WN 的周期性和对称性,把一个N 项序列(设N=2k,k 为正整数),分为两个N/2项的子序列,每个N/2点DFT 变换需要(N/2)2次运算,再用N 次运算把两个N/2点的DFT 变换组合成一个N 点的DFT 变换。
FFT的C语言算法实现
FFT的C语言算法实现程序如下:/************FFT***********/#include <stdio.h>#include <math.h>#include <stdlib.h>#define N 1000typedef struct{double real;double img;}complex;void fft(); /*快速傅里叶变换*/void ifft(); /*快速傅里叶逆变换*/void initW();void change();void add(complex ,complex ,complex *); /*复数加法*/void mul(complex ,complex ,complex *); /*复数乘法*/void sub(complex ,complex ,complex *); /*复数减法*/void divi(complex ,complex ,complex *);/*复数除法*/void output(); /*输出结果*/complex x[N], *W;/*输出序列的值*/int size_x=0;/*输入序列的长度,只限2的N次方*/ double PI;int main(){int i,method;system("cls");PI=atan(1)*4;printf("Please input the size of x:\n");/*输入序列的长度*/scanf("%d",&size_x);printf("Please input the data in x[N]:(such as:5 6)\n");/*输入序列对应的值*/for(i=0;i<size_x;i++)scanf("%lf %lf",&x[i].real,&x[i].img);initW();/*选择FFT或逆FFT运算*/printf("Use FFT(0) or IFFT(1)?\n");scanf("%d",&method);if(method==0)fft();elseifft();output();return 0;}/*进行基-2 FFT运算*/void fft(){int i=0,j=0,k=0,l=0;complex up,down,product;change();for(i=0;i< log(size_x)/log(2) ;i++) {l=1<<i;for(j=0;j<size_x;j+= 2*l ){for(k=0;k<l;k++){mul(x[j+k+l],W[size_x*k/2/l],&product); add(x[j+k],product,&up);sub(x[j+k],product,&down);x[j+k]=up;x[j+k+l]=down;}}}}void ifft(){int i=0,j=0,k=0,l=size_x;complex up,down;for(i=0;i< (int)( log(size_x)/log(2) );i++) /*蝶形运算*/{l/=2;for(j=0;j<size_x;j+= 2*l ){for(k=0;k<l;k++){add(x[j+k],x[j+k+l],&up);up.real/=2;up.img/=2;sub(x[j+k],x[j+k+l],&down);down.real/=2;down.img/=2;divi(down,W[size_x*k/2/l],&down);x[j+k]=up;x[j+k+l]=down;}}}change();}void initW(){int i;W=(complex *)malloc(sizeof(complex) * size_x); for(i=0;i<size_x;i++){W[i].real=cos(2*PI/size_x*i);W[i].img=-1*sin(2*PI/size_x*i);}}void change(){complex temp;unsigned short i=0,j=0,k=0;double t;for(i=0;i<size_x;i++){k=i;j=0;t=(log(size_x)/log(2));while( (t--)>0 ){j=j<<1;j|=(k & 1);k=k>>1;}if(j>i){temp=x[i];x[i]=x[j];x[j]=temp;}}}void output() /*输出结果*/{int i;printf("The result are as follows\n"); for(i=0;i<size_x;i++){printf("%.4f",x[i].real);if(x[i].img>=0.0001)printf("+%.4fj\n",x[i].img);else if(fabs(x[i].img)<0.0001)printf("\n");elseprintf("%.4fj\n",x[i].img);}}void add(complex a,complex b,complex *c) {c->real=a.real+b.real;c->img=a.img+b.img;}void 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;}void sub(complex a,complex b,complex *c) {c->real=a.real-b.real;c->img=a.img-b.img;}void divi(complex a,complex b,complex *c) {c->real=( a.real*b.real+a.img*b.img )/(b.real*b.real+b.img*b.img);c->img=( a.img*b.real-a.real*b.img)/(b.real*b.real+b.img*b.i mg);}。
fft c语言程序
fft c语言程序快速傅里叶变换(Fast Fourier Transform,FFT)是一种计算机算法,它能够将一个离散的时间域信号转换为频谱域信号。
FFT算法是一种高效的计算傅里叶变换的方法,可以大大加快计算速度。
FFT算法是由高效的分治策略设计得来的。
它将傅里叶变换的计算分解为多个较小规模的子问题,然后逐步合并这些子问题的计算结果,最终得到原始问题的解。
因此,FFT算法的时间复杂度为O(n log n),其中n表示信号的长度。
相比之下,传统的傅里叶变换算法的时间复杂度为O(n^2),因此FFT算法在处理大规模信号时具有较大的优势。
在C语言中,我们可以使用库函数来实现FFT算法。
这些库函数通常提供了一些基本的操作,例如初始化FFT对象、进行离散傅里叶变换、进行逆变换等。
以下是一个简单的C语言程序,用于实现FFT算法:```c#include <stdio.h>#include <stdlib.h>#include <math.h>#include <complex.h>//计算离散傅里叶变换void fft(double complex buf[], int n){if (n <= 1)return;double complex *even = malloc(n / 2 * sizeof(double complex));double complex *odd = malloc(n / 2 * sizeof(double complex));for (int i = 0; i < n / 2; i++){even[i] = buf[2 * i];odd[i] = buf[2 * i + 1];}fft(even, n / 2);fft(odd, n / 2);for (int k = 0; k < n / 2; k++){double complex t = cexp(-I * 2 * M_PI * k / n) * odd[k]; buf[k] = even[k] + t;buf[k + n / 2] = even[k] - t;}free(even);free(odd);}//打印复数数组void print_complex(double complex buf[], int n){for (int i = 0; i < n; i++){printf("%.2f + %.2fi\n", creal(buf[i]), cimag(buf[i]));}}int main(void){int n = 8;double complex buf[] = {1.0 + 0.0 * I, 1.0 + 0.0 * I, 1.0 + 0.0 * I, 1.0 + 0.0 * I,0.0 + 0.0 * I, 0.0 + 0.0 * I, 0.0 + 0.0 * I, 0.0 + 0.0 * I};fft(buf, n);print_complex(buf, n);return 0;}```这个程序定义了两个函数:`fft`和`print_complex`。
快速傅里叶变换c++实现
快速傅里叶变换 c++实现
以下是一个使用 C++实现快速傅里叶变换(FFT)的示例代码。在这个实现中,
我们使用了递归的 FFT 算法,对于 n 个点的输入信号,其时间复杂度为 O(nlogn)。
#include <iostream> #include <complex> #include <vector> using namespace std;
even[i] = x[2 * i]; odd[i] = x[2 * i + 1]; } // 递归调用 FFT 函数 fft(even, inv); fft(odd, inv); // 计算 Wn 和 W-n Complex wn = exp(-2 * I * inv * M_PI / n) * inv; for (int i = 0; i < n / 2; i++) { x[i] = even[i] + wn * odd[i]; x[i + n / 2] = even[i] - wn * odd[i]; } }
快速傅里叶算法C语言完整实现
#inclu de<st dio.h>#in clude<math.h>#defin e ui nt un signe d int#def ine uchar unsi gnedchartyped ef st ructCompl ex//复数结构体{dou ble R e;do ubleIm;}Compl ex;C omple x Mul(Comp lex a,Comp lex b)//复数相乘{Compl ex c;c.Re=a.Re*b.Re-a.Im*b.Im;c.I m=a.R e*b.I m+a.I m*b.R e;re turnc;}Compl ex Pl us(Co mplex a,Co mplex b)//复数相加{Com plexc;c.Re=a.Re+b.Re;c.Im=a.Im+b.Im;retur n c;}Com plexSub(C omple x a,C omple x b)//复数相减{Co mplex c;c.Re=a.Re-b.Re;c.Im=a.Im-b.Im;retu rn c;}/*********************************************************************** *******************函数说明:倒序运算参数说明:N点数,等于2的M次方,*x序列的首地址返回值:无******************************************************************************************/v oid I nvert_orde r(uin t N,C omple x *x,uchar M){uin t pow er,i,j,m,t empp;//m是i的倒位序数Com plextemp;//是临时变量f or(i=0;i<N;i++){powe r=1;m=0;f or(j=0;j<M;j++){te mpp=i;tempp>>=(M-1-j);if(te mpp&0x01){m=m+po wer;}po wer=p ower*2;}i f(i<m){t emp.I m=(x+i)->I m;temp.Re=(x+i)->Re;(x+i)->Re=(x+m)->Re;(x+i)->I m=(x+m)->I m;(x+m)->Im=temp.Im;(x+m)->Re=te mp.Re;}}}/*********************************************************************** *******************In vert_order函数结束:************************************************************************ ******************//*********************************************************************** *******************函数说明:指数运算参数说明:Base Numbe r底数,I ndexN umber指数返回值:无符号整数************************************************************************ ******************/uintPow(u charBaseN umber,uint Inde xNumb er){uin t m=1;//指数函数值uchar i;for(i=0;i<Index Numbe r;i++){m=B aseNu mber*m;}ret urn m;}/*********************************************************************** *******************Pow函数结束:************************************************************************ ******************//******************************************************************************************函数说明:对数运算参数说明:B aseNu mber底数,Ant iNumb er真数返回值:无符号整数************************************************************************ ******************/uin t Log(ucha r Bas eNumb er,ui nt An tiNum ber){ui nt m=0;//对数函数值whil e(1){AntiN umber=Anti Numbe r/Bas eNumb er;if(A ntiNu mber)m++;els e bre ak; }r eturn m;}/*********************************************************************** *******************lo g函数结束:******************************************************************************************//*********************************************************************** *******************函数说明:按时间抽取基二快速傅里叶算法参数说明:N点数,等于2的M次方,*x序列的首地址返回值:无************************************************************************ ******************/void Dit2Fft(u int N,Comp lex *x){intclk=0;Com plextemp;//临时复数变量u int L,M=Lo g(2,N);//M级蝶形图uintk,j;uintStepL ength;//k值步长ui nt Ba nk ;//两点间的距离co nst d ouble pai=3.1415926;doub le ps;uin t r;//旋转因子的幂C omple x W;//旋转因子prin tf("M de z hi sh i :M=%u\n",M);for(L=1;L<=M;L++){Step Lengt h=Pow(2,L);Ba nk=St epLen gth/2;pr intf("L=%u\tSte p=%u\tBank=%u\n",L,S tepLe ngth,Bank);fo r(j=0;j<=B ank-1;j++){Comp lex W_temp;W_temp.Im=-1.0;W_t emp.R e=1.0;r=Pow(2,M-L)*j ;ps=2*pa i/N*r ;W.Re=cos(p s);W.Im=-sin(ps);//W.Re=ps;// W.Im=10.0*ps;for(k=j;k<=N-1;k=k+Step Lengt h){Co mplex x_te mp;pri ntf("%u\n",r);x_temp=Mul(W,x[k+Bank]);temp=Plus(x[k],x_tem p);x[k+Bank]=Sub(x[k],x_te mp);x[k].R e=tem p.Re; x[k].Im=temp.Im;}}//prin tf("z hu yi le:c lk=%d\n",c lk);}}/*********************************************************************** *******************Dit2Fft函数结束:************************************************************************ ******************/#if1#d efine DATA_LEN16vo id ma in(){ui nt N,M;i nt i;Com plexx[DAT A_LEN];N=DATA_LEN;M=L og(2,N);print f("ch u shi xu l ie:\n");for(i=0;i<DATA_LEN;i++)//序列初始化{x[i].Im=0;x[i].Re=i;}pr intf("\n");In vert_order(N,x,M);print f("da o xuhou xu li e:\n");f or(i=0;i<D ATA_L EN;i++)//倒序后再次输出{prin tf("%lf %l f ",x[i].R e,x[i].Im);if(i%2==0)pr intf("\n");}prin tf("\n");Dit2Fft(N,x);prin tf("F FT yu n sua n hou xu l ie:\n");for(i=0;i<DATA_LEN;i++)//FFT后再次输出{//print f("%l f+%lf i\t\t",x[i].Re,x[i].Im);//pri ntf("%lf\t",x[i].Im);//if(i%2==0)print f("\n");}//print f("\n");pri ntf("After...\n Real\t\tIm ag\n");for(i=0;i<DATA_LEN;i++)//FFT后再次输出{pr intf("%f\t%f\t\n",x[i].Re,x[i].Im);// p rintf("%f\n",sq rt(x[i].Re*x[i].Re+x[i].I m*x[i].Im));}// p rintf("\n");}#end if。
快速傅立叶算法的C语言实现
快速傅立叶算法的C语言实现#include "math.h"void kfft(pr,pi,n,k,fr,fi,l,il)int n,k,l,il;double pr[],pi[],fr[],fi[];{ int it,m,is,i,j,nv,l0;double p,q,s,vr,vi,poddr,poddi;for (it=0; it<=n-1; it++){ m=it; is=0;for (i=0; i<=k-1; i++){ j=m/2; is=2*is+(m-2*j); m=j;}fr[it]=pr[is]; fi[it]=pi[is];}pr[0]=1.0; pi[0]=0.0;p=6.283185306/(1.0*n);pr[1]=cos(p); pi[1]=-sin(p);if (l!=0) pi[1]=-pi[1];for (i=2; i<=n-1; i++){ p=pr[i-1]*pr[1]; q=pi[i-1]*pi[1];s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);pr[i]=p-q; pi[i]=s-p-q;}for (it=0; it<=n-2; it=it+2){ vr=fr[it]; vi=fi[it];fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1]; }m=n/2; nv=2;for (l0=k-2; l0>=0; l0--){ m=m/2; nv=2*nv;for (it=0; it<=(m-1)*nv; it=it+nv)for (j=0; j<=(nv/2)-1; j++){ p=pr[m*j]*fr[it+j+nv/2];q=pi[m*j]*fi[it+j+nv/2];s=pr[m*j]+pi[m*j];s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]); poddr=p-q; poddi=s-p-q;fr[it+j+nv/2]=fr[it+j]-poddr;fi[it+j+nv/2]=fi[it+j]-poddi;fr[it+j]=fr[it+j]+poddr;fi[it+j]=fi[it+j]+poddi;}}if (l!=0)for (i=0; i<=n-1; i++){ fr[i]=fr[i]/(1.0*n);fi[i]=fi[i]/(1.0*n);}if (il!=0)for (i=0; i<=n-1; i++){ pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]);if (fabs(fr[i])<0.000001*fabs(fi[i])){ if ((fi[i]*fr[i])>0) pi[i]=90.0;else pi[i]=-90.0;}elsepi[i]=atan(fi[i]/fr[i])*360.0/6.283185306;}return;}这是在PIC18F458里用的FFT程序/* ************************************************************************** 函数名:void ADCHD()** 功能描述:单通道高频采样,数据处理,显示.*************************************************************************** */ void ADCHD(){long D,SHU; //数据.int n_x,k_x,i; //循环参数.float Ur,Ui,Urn,Uin; //数据处理中间变量.ADWORDS=ADCAN+7; //确定MAX197控制字.for(ADD=0;ADD<64;ADD++) //采样.{OUTADC(ADWORDS); //送控制字.DELAY(0); //延时.DA TA[0][ADD]=INADC(); //读取数据.}for(ADD=0;ADD<64;ADD++) //显示波形.{D=(int)(40.0*DATA[0][ADD]/4096.0); //取数据.LCDPIEX(ADD+64,40-D); //显示.}{Urn=0.0; //实部.Uin=0.0; //虚部.for(k_x=0;k_x<32;k_x++) //n_x次谐波.{D=DATA[0][k_x]; //取数据计算.Urn=Urn+D/409.6*cos((2*n_x+1)*(k_x+1)*0.196);Uin=Uin+D/409.6*sin((2*n_x+1)*(k_x+1)*0.196);}Ur=Urn/16.0; //Ui=Uin/16.0; //SHU=(long)(100*sqrt(Ur*Ur+Ui*Ui));UI[0][n_x]=SHU; //第n_x次谐波幅值.UI[0][5]=SHU*SHU+UI[0][5]; //}UI[0][5]=(long)sqrt(UI[0][5]); //总幅值.for(i=0;i<5;i++) //{SHU=UI[0][i]*1000; //SHU=SHU/(UI[0][5]); //UP[0][i]=SHU; //第i次谐波占有率.}SHU=1000*(UI[0][5]-UI[0][0]); //UP[0][5]=SHU/UI[0][5]; //畸变率.LCDCLEAN(12,2,126,7); //清除数据显示区.for(i=0;i<6;i++){OUTNUM(UI[0][i],1,28,2+i); //显示幅值.OUTNUM(UP[0][i],3,56,2+i); //显示占有率.}ADWORDS=ADCAN; //还原控制字.}/* ************************************************************************** 函数名:void XBFX()** 功能描述:全周波傅立叶积分计算各次谐波的幅值,并返回结果.*************************************************************************** */ void XBFX(){long D,SHU; //数据.int n_x,k_x,i,n; //循环参数.float Ur,Ui,Urn,Uin,UIL[2]; //数据处理中间变量.for(n=0;n<2;n++) //两路信号.{{Urn=0.0; //实部.Uin=0.0; //虚部.for(k_x=0;k_x<32;k_x++) //n_x次谐波.{D=DATA[CHAN*2+n][k_x]; //取数据计算.Urn=Urn+D/409.6*cos((2*n_x+1)*(k_x+1)*0.196);Uin=Uin+D/409.6*sin((2*n_x+1)*(k_x+1)*0.196);}Ur=Urn/16.0; //Ui=Uin/16.0;SHU=(long)(760*sqrt(Ur*Ur+Ui*Ui)); //UI[n][n_x]=SHU; //UI[n][5]=SHU*SHU+UI[n][5]; //第n_x次谐波幅值.if(n_x==0)UIL[n]=atan(Ui/Ur); //相位.}UI[n][5]=(long)sqrt(UI[n][5]); //总幅值.for(i=0;i<5;i++) //{SHU=UI[n][i]*1000; //SHU=SHU/(UI[n][5]); //UP[n][i]=SHU; //第i次谐波占有率.}SHU=1000*(UI[n][5]-UI[n][0]); //UP[n][5]=SHU/UI[n][5]; //畸变率.}L[CHAN]=abs((long)(1000*(UIL[0]-UIL[1])-40)); //功率因数角. S[CHAN]=(long)(UI[0][5]*UI[1][5]); //S.P[CHAN]=(long)(S[CHAN]*cos(L[CHAN]/1000.0)); //P.Q[CHAN]=(long)(S[CHAN]*sin(L[CHAN]/1000.0)); //Q.}。
(快速傅里叶变换)C语言程序
#include<iom128.h>#include<intrinsics.h>/********************************************************************* 快速傅立叶变换C函数函数简介:此函数是通用的快速傅里叶变换C语言函数,移植性强,以下部分不依赖硬件。
此函数采用联合体的形式表示一个复数,输入为自然顺序的复数(输入实数是可令复数虚部为0),输出为经过FFT变换的自然顺序的复数使用说明:使用此函数只需更改宏定义FFT_N的值即可实现点数的改变,FFT_N 应该为2的N次方,不满足此条件时应在后面补0函数调用:FFT(s);时间:2010-2-20版本:Ver1.0参考文献:**********************************************************************/ #include<math.h>#defineFFT_N128//定义傅立叶变换的点数structcompx{floatreal,imag;};//定义一个复数结构structcompxs[FFT_N];//FFT输入和输出:从S[1]开始存放,根据大小自己定义/*******************************************************************函数原型:structcompxEE(structcompxb1,structcompxb2)函数功能:对两个复数进行乘法运算输入参数:两个以联合体定义的复数a,b输出参数:a和b的乘积,以联合体的形式输出*******************************************************************/ structcompxEE(structcompxa,structcompxb){structcompxc;c.real=a.real*b.real-a.imag*b.imag;c.imag=a.real*b.imag+a.imag*b.real;return(c);}/*****************************************************************函数原型:voidFFT(structcompx*xin,intN)函数功能:对输入的复数组进行快速傅里叶变换(FFT)输入参数:*xin复数结构体组的首地址指针,struct型*****************************************************************/ voidFFT(structcompx*xin){intf,m,nv2,nm1,i,k,l,j=0;structcompxu,w,t;nv2=FFT_N/2;//变址运算,即把自然顺序变成倒位序,采用雷德算法nm1=FFT_N-1;for(i=0;i<nm1;i++){if(i<j)//如果i<j,即进行变址{t=xin[j];xin[j]=xin[i];xin[i]=t;}k=nv2;//求j的下一个倒位序while(k<=j)//如果k<=j,表示j的最高位为1{j=j-k;//把最高位变成0k=k/2;//k/2,比较次高位,依次类推,逐个比较,直到某个位为0}j=j+k;//把0改为1}{intle,lei,ip;//FFT运算核,使用蝶形运算完成FFT运算f=FFT_N;for(l=1;(f=f/2)!=1;l++);//计算l的值,即计算蝶形级数for(m=1;m<=l;m++)//控制蝶形结级数{//m表示第m级蝶形,l为蝶形级总数l=log(2)Nle=2<<(m-1);//le蝶形结距离,即第m级蝶形的蝶形结相距le点lei=le/2;//同一蝶形结中参加运算的两点的距离u.real=1.0;//u为蝶形结运算系数,初始值为1u.imag=0.0;w.real=cos(PI/lei);//w为系数商,即当前系数与前一个系数的商w.imag=-sin(PI/lei);for(j=0;j<=lei-1;j++)//控制计算不同种蝶形结,即计算系数不同的蝶形结{for(i=j;i<=FFT_N-1;i=i+le)//控制同一蝶形结运算,即计算系数相同蝶形结{ip=i+lei;//i,ip分别表示参加蝶形运算的两个节点t=EE(xin[ip],u);//蝶形运算,详见公式xin[ip].real=xin[i].real-t.real;xin[ip].imag=xin[i].imag-t.imag;xin[i].real=xin[i].real+t.real;xin[i].imag=xin[i].imag+t.imag;}u=EE(u,w);//改变系数,进行下一个蝶形运算}}}}/************************************************************函数原型:voidmain()函数功能:测试FFT变换,演示函数使用方法输入参数:无输出参数:无************************************************************/ voidmain(){inti;for(i=0;i<FFT_N;i++)//给结构体赋值{s[i].imag=0;//虚部为0}FFT(s);//进行快速傅立叶变换for(i=0;i<FFT_N;i++)//求变换后结果的模值,存入复数的实部部分s[i].real=sqrt(s[i].real*s[i].real+s[i].imag*s[i].imag); while(1);}#include<iom128.h>#include<intrinsics.h>/*********************************************************************快速傅立叶变换C程序包函数简介:此程序包是通用的快速傅里叶变换C语言函数,移植性强,以下部分不依赖硬件。
C语言编写FFT程序
DSP 课程作业用C 语言编写FFT 程序1,快速傅里叶变换FFT 简介快速傅氏变换(FFT ),是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。
它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。
我们假设 x(n)为N 项的复数序列,由DFT 变换,任一X (m )的计算都需要N 次复数乘法和N-1次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法,即使把一次复数乘法和一次复数加法定义成一次“运算”(四次实数乘法和四次实数加法),那么求出N 项复数序列的X (m ),即N 点DFT 变换大约就需要N^2次运算。
当N=1024点甚至更多的时候,需要N2=1048576次运算,在FFT 中,利用WN 的周期性和对称性,把一个N 项序列(设N=2k,k 为正整数),分为两个N/2项的子序列,每个N/2点DFT 变换需要(N/2)2次运算,再用N 次运算把两个N/2点的DFT 变换组合成一个N 点的DFT 变换。
这样变换以后,总的运算次数就变成N+2(N/2)2=N+N2/2。
继续上面的例子,N=1024时,总的运算次数就变成了525312次,节省了大约50%的运算量。
而如果我们将这种“一分为二”的思想不断进行下去,直到分成两两一组的DFT 运算单元,那么N 点的DFT 变换就只需要Nlog2N 次的运算,N 在1024点时,运算量仅有10240次,是先前的直接算法的1%,点数越多,运算量的节约就越大,这就是FFT 的优越性。
2,FFT 算法的基本原理FFT 算法的基本思想:利用DFT 系数的特性,合并DFT 运算中的某些项,吧长序列的DFT —>短序列的DFT ,从而减少其运算量。
FFT 算法分类:时间抽选法DIT: Decimation-In-Time ;频率抽选法DIF: Decimation-In-Frequency按时间抽选的基-2FFT 算法1、算法原理设序列点数 N = 2L ,L 为整数。
快速傅里叶算法C语言完整实现
快速傅里叶算法C语言完整实现#include<stdio.h>#include<math.h>#define uint unsigned int#define uchar unsigned chartypedef struct Complex//复数结构体{double Re;double Im;}Complex;Complex Mul(Complex a,Complex b)//复数相乘{Complex c;c.Re=a.Re*b.Re-a.Im*b.Im;c.Im=a.Re*b.Im+a.Im*b.Re;return c;}Complex Plus(Complex a,Complex b)//复数相加{Complex c;c.Re=a.Re+b.Re;c.Im=a.Im+b.Im;return c;}Complex Sub(Complex a,Complex b)//复数相减{Complex c;c.Re=a.Re-b.Re;c.Im=a.Im-b.Im;return c;}/********************************************************************** ********************函数说明:倒序运算参数说明:N点数,等于2的M次方,*x序列的首地址返回值:无*********************************************************************** *******************/void Invert_order(uint N,Complex*x,uchar M){uint power,i,j,m,tempp;//m是i的倒位序数Complex temp;//是临时变量for(i=0;i<N;i++){power=1;m=0;for(j=0;j<M;j++){tempp=i;tempp>>=(M-1-j);if(tempp&0x01){m=m+power;}power=power*2;}if(i<m){temp.Im=(x+i)->Im;temp.Re=(x+i)->Re;(x+i)->Re=(x+m)->Re;(x+i)->Im=(x+m)->Im;(x+m)->Im=temp.Im;(x+m)->Re=temp.Re;}}}/********************************************************************** ********************Invert_order函数结束:*********************************************************************** *******************//********************************************************************** ********************函数说明:指数运算参数说明:BaseNumber底数,IndexNumber指数返回值:无符号整数*********************************************************************** *******************/uint Pow(uchar BaseNumber,uint IndexNumber){uint m=1;//指数函数值uchar i;for(i=0;i<IndexNumber;i++){m=BaseNumber*m;}return m;}/********************************************************************** ********************Pow函数结束:*********************************************************************** *******************//********************************************************************** ********************函数说明:对数运算参数说明:BaseNumber底数,AntiNumber真数返回值:无符号整数*********************************************************************** *******************/uint Log(uchar BaseNumber,uint AntiNumber){uint m=0;//对数函数值while(1){AntiNumber=AntiNumber/BaseNumber;if(AntiNumber)m++;else break;}return m;}/********************************************************************** ********************log函数结束:*********************************************************************** *******************//********************************************************************** ********************函数说明:按时间抽取基二快速傅里叶算法参数说明:N点数,等于2的M次方,*x序列的首地址返回值:无*********************************************************************** *******************/void Dit2Fft(uint N,Complex*x){int clk=0;Complex temp;//临时复数变量uint L,M=Log(2,N);//M级蝶形图uint k,j;uint StepLength;//k值步长uint Bank;//两点间的距离const double pai=3.1415926;double ps;uint r;//旋转因子的幂Complex W;//旋转因子printf("M de zhi shi:M=%u\n",M);for(L=1;L<=M;L++){StepLength=Pow(2,L);Bank=StepLength/2;printf("L=%u\tStep=%u\tBank=%u\n",L,StepLength,Bank); for(j=0;j<=Bank-1;j++){Complex W_temp;W_temp.Im=-1.0;W_temp.Re=1.0;r=Pow(2,M-L)*j;ps=2*pai/N*r;W.Re=cos(ps);W.Im=-sin(ps);//W.Re=ps;//W.Im=10.0*ps;for(k=j;k<=N-1;k=k+StepLength){Complex x_temp;printf("%u\n",r);x_temp=Mul(W,x[k+Bank]);temp=Plus(x[k],x_temp);x[k+Bank]=Sub(x[k],x_temp);x[k].Re=temp.Re;x[k].Im=temp.Im;}}//printf("zhu yi le:clk=%d\n",clk);}}/********************************************************************** ********************Dit2Fft函数结束:*********************************************************************** *******************/#if1#define DATA_LEN16void main(){uint N,M;int i;Complex x[DATA_LEN];N=DATA_LEN;M=Log(2,N);printf("chu shi xu lie:\n");for(i=0;i<DATA_LEN;i++)//序列初始化{x[i].Im=0;x[i].Re=i;}printf("\n");Invert_order(N,x,M);printf("dao xu hou xu lie:\n");for(i=0;i<DATA_LEN;i++)//倒序后再次输出{printf("%lf%lf",x[i].Re,x[i].Im);if(i%2==0)printf("\n");}printf("\n");Dit2Fft(N,x);printf("FFT yun suan hou xu lie:\n");for(i=0;i<DATA_LEN;i++)//FFT后再次输出{//printf("%lf+%lfi\t\t",x[i].Re,x[i].Im);//printf("%lf\t",x[i].Im);//if(i%2==0)printf("\n");}//printf("\n");printf("After...\nReal\t\tImag\n");for(i=0;i<DATA_LEN;i++)//FFT后再次输出{printf("%f\t%f\t\n",x[i].Re,x[i].Im);//printf("%f\n",sqrt(x[i].Re*x[i].Re+x[i].Im*x[i].Im)); }//printf("\n");}#endif。
快速傅里叶变换C语言程序
快速傅里叶变换C语言程序#include <>/************************************************************** *******快速傅立叶变换C函数函数简介:此函数是通用的快速傅里叶变换C语言函数,移植性强,以下部分不依赖硬件。
此函数采用联合体的形式表示一个复数,输入为自然顺序的复数(输入实数是可令复数虚部为0),输出为经过FFT变换的自然顺序的复数使用说明:使用此函数只需更改宏定义FFT_N的值即可实现点数的改变,FFT_N应该为2的N次方,不满足此条件时应在后面补0函数调用:FFT(s);时间:2010-2-20版本:参考文献:*************************************************************** *******/#include<>#define PI eal=xin[i].;xin[ip].imag=xin[i].;xin[i].real=xin[i].real+;xin[i].imag=xin[i].imag+;}u=EE(u,w); eal=sin(2**i/FFT_N); mag=0; eal=sqrt(s[i].real*s[i].real+s[i].imag*s[i].imag);while(1);}#include <>/************************************************************** *******快速傅立叶变换C程序包函数简介:此程序包是通用的快速傅里叶变换C语言函数,移植性强,以下部分不依赖硬件。
此程序包采用联合体的形式表示一个复数,输入为自然顺序的复数(输入实数是可令复数虚部为0),输出为经过FFT变换的自然顺序的复数.此程序包可在初始化时调用create_sin_tab()函数创建正弦函数表,以后的可采用查表法计算耗时较多的sin和cos运算,加快可计算速度使用说明:使用此函数只需更改宏定义FFT_N的值即可实现点数的改变,FFT_N应该为2的N次方,不满足此条件时应在后面补0。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
printf("dao xu hou xu lie:\n");
for(i=0;i<DATA_LEN;i++)//倒序后再次输出
{
printf("%lf %lf ",x[i].Re,x[i].Im);
if(i%2==0)printf("\n");
x[k+Bank]=Sub(x[k],x_temp);
x[k].Re=temp.Re; x[k].Biblioteka m=temp.Im; }
}
//printf("zhu yi le:clk=%d\n",clk);
}
}
/******************************************************************************************
printf("%f\t%f\t\n",x[i].Re,x[i].Im);
// printf("%f\n",sqrt(x[i].Re*x[i].Re+x[i].Im*x[i].Im));
}
// printf("\n");
}
#endif
for(j=0;j<=Bank-1;j++)
{
Complex W_temp;
W_temp.Im=-1.0;
W_temp.Re=1.0;
r=Pow(2,M-L)*j ;
ps=2*pai/N*r ;
W.Re=cos(ps);
W.Im=-sin(ps);
// W.Re=ps;
#include<stdio.h>
#include<math.h>
#define uint unsigned int
#define uchar unsigned char
typedef struct Complex//复数结构体
{
double Re;
double Im;
}Complex;
log函数结束:
******************************************************************************************/
/******************************************************************************************
void Invert_order(uint N,Complex *x,uchar M)
{
uint power,i,j,m,tempp;//m是i的倒位序数
Complex temp;//是临时变量
for(i=0;i<N;i++)
{
power=1;
m=0;
for(j=0;j<M;j++)
函数说明:按时间抽取基二快速傅里叶算法
参数说明:N点数,等于2的M次方,*x序列的首地址
返回值:无
******************************************************************************************/
void Dit2Fft(uint N,Complex *x)
int i;
Complex x[DATA_LEN];
N=DATA_LEN;
M=Log(2,N);
printf("chu shi xu lie:\n");
for( i=0;i<DATA_LEN;i++)//序列初始化
{
x[i].Im=0;
x[i].Re=i;
}
printf("\n");
}
printf("\n");
Dit2Fft(N,x);
printf("FFT yun suan hou xu lie:\n");
for(i=0;i<DATA_LEN;i++)//FFT后再次输出
{
// printf("%lf+%lfi\t\t",x[i].Re,x[i].Im);
{
uint m=1;//指数函数值
uchar i;
for(i=0;i<IndexNumber;i++)
{
m=BaseNumber*m;
}
return m;
}
/******************************************************************************************
函数说明:指数运算
参数说明:BaseNumber底数,IndexNumber指数
返回值:无符号整数
******************************************************************************************/
uint Pow(uchar BaseNumber,uint IndexNumber)
//printf("%lf\t",x[i].Im);
// if(i%2==0)printf("\n");
}
// printf("\n");
printf("After...\nReal\t\tImag\n");
for(i=0;i<DATA_LEN;i++)//FFT后再次输出
{
}
/******************************************************************************************
函数说明:倒序运算
参数说明:N点数,等于2的M次方,*x序列的首地址
返回值:无
******************************************************************************************/
{
int clk=0;
Complex temp;//临时复数变量
uint L,M=Log(2,N);//M级蝶形图
uint k,j;
uint StepLength;//k值步长
uint Bank ;//两点间的距离
const double pai=3.1415926;
double ps;
函数说明:对数运算
参数说明:BaseNumber底数,AntiNumber真数
返回值:无符号整数
******************************************************************************************/
uint Log(uchar BaseNumber,uint AntiNumber)
{
uint m=0;//对数函数值
while(1)
{
AntiNumber=AntiNumber/BaseNumber;
if(AntiNumber)m++;
else break;
}
return m;
}
/******************************************************************************************
// W.Im=10.0*ps;
for(k=j;k<=N-1;k=k+StepLength)
{
Complex x_temp;
printf("%u\n",r);
x_temp=Mul(W,x[k+Bank]);
temp=Plus(x[k],x_temp);
Dit2Fft函数结束:
******************************************************************************************/
#if 1
#define DATA_LEN 16
void main()
{
uint N,M;
uint r;//旋转因子的幂
Complex W;//旋转因子
printf("M de zhi shi :M=%u\n",M);
for(L=1;L<=M;L++)
{
StepLength=Pow(2,L);
Bank=StepLength/2;
printf("L=%u\tStep=%u\tBank=%u\n",L,StepLength,Bank);
Pow函数结束:
******************************************************************************************/
/******************************************************************************************