几种快速傅里叶变换(FFT)的C++实现
链接:http://blog.csdn.net/zwlforever/archive/2008/03/14/2183049.aspx
一篇不错的FFT 文章,收藏一下。
DFT的的正变换和反变换分别为(1)和(2)式。假设有N个数据,则计算一个频率点需要N次复数乘法和N-1次复数加法,整个DFT需要N*N次复数乘法和N(N-1)次复数加法;由于一次的复数乘法需要进行4次的实数乘法和2次的复数加法,一次的复数加法需要两次的实数加法,因此整个DFT需要4*N*N次的实数乘法和2*N(N-1)+2*N*N≈4*N*N次的复数加法。当N比较大时,所需的计算工作量相当大,例如N=1024时大约需要400万次乘法运算,对于实时信号处理来说,将对计算设备提出非常苛刻的要求,于是就提出如何能够减少计算DFT的运算量的问题。
大多数的FFT算法都是利用(3)式的周期性、共轭对称性、可压缩和扩展性的特点来压缩计算量。。
1)、根据DFT定义进行计算的代码
void dft(complex<double>*Data,int Log2N,int flag)
{
int i,j,length;
complex<double> wn;
length=1<<Log2N;
complex<double>*temp=new complex<double>(length);
for(i=0;i<length;i++)
{
temp[i]=0;
for(j=0;j<length;j++)
{
wn=complex<double>(cos(2.0*pi/length*i*j),sin(flag*2.0*pi/length*i*j));
temp[i]+=Data[j]*wn;
}
}
if(flag==1)
for(i=0;i<length;i++)
Data[i]=temp[i]/length;
delete[] temp;
}
2)、基2时间抽选FFT
把时域的数字信号序列按照奇偶进行分组计算,可以进行如下的变换,从变换结果可以知道,一个长度为N的DFT可以变换成长度为N/2的两个子序列的组合。依次类推,可以直到转为N/2个2点的傅立叶变化的组合。不过这时的输入应该为以2为基的倒位序。
由于经过多次的奇偶抽选,输入数据要按照基2倒序的原则进行重排,输出数据为正常顺序,倒序算法另外叙述。下面首先用递归的形式进行算法的描述,由于递归方法没有充分利用DIT2算法的优点---原位计算,因此递归形式只是为了描述的清晰。
{
complex<double>*EvenData=new complex<double>(length/2);
complex<double>*OddData =new complex<double>(length/2);
complex<double>*EvenResult=new complex<double>(length/2);
complex<double>*OddResult=new complex<double>(length/2);
int i,j;
if(length==1)
{
OutData[0]=InData[0]/N;
return;
}
for(i=0;i<length/2;i++)
{
EvenData[i]=InData[2*i];
OddData[i]=InData[2*i+1];
}
dit2rec(EvenData,EvenResult,length/2,sign);
dit2rec(OddData,EvenResult,length/2,sign);
for(i=0;i<length/2;i++)
{
OutData[i]=EvenData+OddData*complex<double>(cos(2*pi*i/length),sin(sign*2*pi*i/length));
OutData[i+length/2]=EvenData- OddData*complex<double>(cos(2*pi*i/length),sin(sign*2*pi*i/length));
}
delete[] EvenData,OddData,EvenResult,OddResult;
return;
}
{
int i,j,k,step,length;
complex<double> wn,temp,deltawn;
length=1<<Log2N;
for(i=1;i<=Log2N;i++)
{
wn=1;step=1<<i;deltawn=complex<double>(cos(2*pi/step),sin(sign*2.0*pi/step));
for(j=0;j<step/2;j++)
{
for(i=0;i<length/step;i++)
{
temp=Data[i*step+step/2+j]*wn;
Data[i*step+step/2+j]=Data[i*step+j]-temp;
Data[i*step+j]=Data[i*step+j]+temp;
}
wn=wn*deltawn;
}
}
if(sign==-1)
for(i=0;i<length;i++)
Data[i]/=length;
}
{
int i,j,k,step,length;
complex<double> wn,temp,deltawn;
length=1<<Log2N;
for(i=0;i<length;i+=2)
{
temp=Data[i];
Data[i]=Data[i]+Data[i+1];
Data[i+1]=temp-Data[i+1];
}
for(i=2;i<=Log2N;i++)
{
wn=1;step=1<<i;deltawn=complex<double>(cos(2.0*pi/step),sin(sign*2.0*pi/step));;
for(j=0;j<step/2;j++)
{
for(i=0;i<length/step;i++)
{
temp=Data[i*step+step/2+j]*wn;
Data[i*step+step/2+j]=Data[i*step+j]-temp;
Data[i*step+j]=Data[i*step+j]+temp;
}
wn=wn*deltawn;
}
}
if(sign==1)
for(i=0;i<length;i++)
Data[i]/=length;
}
void dif2rec(complex<double>*InData,complex<double>*OutData,int length,int sign)
{
complex<double>* LData=new complex<double>(length/2);
complex<double>* LResult=new complex<double>(length/2);
complex<double>* RData=new complex<double>(length/2);
complex<double>* RResult=new complex<double>(length/2);
complex<double> temp;
int i;
if(length==1)
{
OutData[0]=InData[0];
return;
}
for(i=0;i<length/2;i++)
{
LData[i]=InData[i];
RData[i]=InData[i+length/2];
}
for(i=0;i<length/2;i++)
{
temp=LData[i];
LData[i]=LData[i]+RData[i];
RData[i]=(temp-RData[i])* complex<double>(cos(2*pi*i/length),sin(sign*2*pi*i/length))
}
dit2rec(LData,LResult,length/2,sign);
dit2rec(RData,RResult,length/2,sign);
for(i=0;i<length/2;i++)
{
OutData[2*i]=LResult[i];
OutData[2*i+1]=RResult[i];
}
return;
}
void dif2(complex<double>*InData,int r,int sign)
{
int length=1<<r;
int i,j,k,step;
complex<double> temp,wn;
for(i=1;i<=r;i++)
{
step=1<<(r-i+1);
wn=1;
for(j=0;j<step/2;j++)
{
for(k=0;k<step/2;k++)
{
temp=InData[k*step+j];
InData[k*step+j]=InData[k*step+j]-InData[k*step+step/2+j];
InData[k*step+step/2+j]=(temp-InData[k*step+step/2+j])*wn;
}
wn=wn*complex<double>(cos(2*pi/step*j),sin(sign*2*pi/step*j));
}
}
}
和DIT一样,最外层的最后一个循环可以另外独立出来,因为最后一个循环没有必要进行复数运算,这样可以减少复数运算的次数。
基四时间抽选快速傅立叶算法
几种快速傅里叶变换(FFT)的C++实现的更多相关文章
- [学习笔记] 多项式与快速傅里叶变换(FFT)基础
引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积, 而代码量却非常小. 博主一年半前曾经因COGS的一 ...
- 快速傅里叶变换FFT& 数论变换NTT
相关知识 时间域上的函数f(t)经过傅里叶变换(Fourier Transform)变成频率域上的F(w),也就是用一些不同频率正弦曲线的加 权叠加得到时间域上的信号. \[ F(\omega)=\m ...
- 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】
原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...
- 快速傅里叶变换(FFT)
扯 去北京学习的时候才系统的学习了一下卷积,当时整理了这个笔记的大部分.后来就一直放着忘了写完.直到今天都腊月二十八了,才想起来还有个FFT的笔记没整完呢.整理完这个我就假装今年的任务全都over了吧 ...
- 快速傅里叶变换(FFT)_转载
FFTFFT·Fast Fourier TransformationFast Fourier Transformation快速傅立叶变换 P3803 [模板]多项式乘法(FFT) 参考上文 首 ...
- 基于python的快速傅里叶变换FFT(二)
基于python的快速傅里叶变换FFT(二)本文在上一篇博客的基础上进一步探究正弦函数及其FFT变换. 知识点 FFT变换,其实就是快速离散傅里叶变换,傅立叶变换是数字信号处理领域一种很重要的算法. ...
- 【学习笔记】快速傅里叶变换(FFT)
[学习笔记]快速傅里叶变换 学习之前先看懂这个 浅谈范德蒙德(Vandermonde)方阵的逆矩阵的求法以及快速傅里叶变换(FFT)中IDFT的原理--gzy hhh开个玩笑. 讲一下\(FFT\) ...
- Algorithm: 多项式乘法 Polynomial Multiplication: 快速傅里叶变换 FFT / 快速数论变换 NTT
Intro: 本篇博客将会从朴素乘法讲起,经过分治乘法,到达FFT和NTT 旨在能够让读者(也让自己)充分理解其思想 模板题入口:洛谷 P3803 [模板]多项式乘法(FFT) 朴素乘法 约定:两个多 ...
- 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT)
再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Bluestein算法+分治FFT+FFT的优化+任意模数NTT) 目录 再探快速傅里叶变换(FFT)学习笔记(其三)(循环卷积的Blueste ...
随机推荐
- Word中使用代码高亮插件
Word中使用代码高亮插件 1.下载并安装:SyntaxHighlighter4Word.zip 解压,然后双击bin\word2010\Kong.SyntaxHighlighter.Word2010 ...
- Java NIO--初步认识
: 一.java NIO 和阻塞I/O的区别 1. 阻塞I/O通信模型 2. java NIO原理及通信模型 二.java NIO服务端和客户端代码实现 一.java NIO 和阻 ...
- Java-Math
java.lang.Math类提供的方法都是static的,“静态引入 ”使得不必每次在调用类方法时都在方法前写上类名: import static java.lang.Mat ...
- 多玩YY聊天记录解析全过程
再来一发,现在开始! 下载安装YY,观察YY目录,很明显的发现了sqlite3.dll,这个数据库很多很多很多软件都在用,简单小巧且开源.删除sqlite3.dll 进入YY,历史记录不能正常显示,基 ...
- list和用vector区别(Vector相当于是数组,读写快,插入慢)
stl提供了三个最基本的容器:vector,list,deque. vector和built-in数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此它能非常好的支持随即存取,即[]操作符,但由 ...
- JVM调优总结(七)-典型配置举例1
以下配置主要针对分代垃圾回收算法而言. 堆大小设置 年轻代的设置很关键 JVM中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理 ...
- Windows Azure 安全最佳实践 - 第 6 部分:Azure 服务如何扩展应用程序安全性
多种Windows Azure服务可以帮助您将应用程序安全性扩展到云. 有三种服务可提供多个提供程序之间的身份标识映射.内部部署数据中心间的连接和相互发送消息的应用程序功能(无论应用程序位于何处). ...
- JAVA_2Lesson
package test; public class abc { public static void main(String[] arg) { int[][] xx=new int[3][]; xx ...
- 【新提醒】N820 N821 android 4.2 V1.1版 - 大V综合交流区 - 360官方论坛
http://bbs.360safe.com/forum.php?mod=viewthread&tid=3088815&extra=page%3D1%26filter%3Dtypeid ...
- MSSQL - Sqlcommand
Command对象:·Command对象也称为数据库连接对象,Command对象主要执行包括添加.删除.修改.查询数据的操作命令.也可以用来执行存储过程. 属性:CommandType属性. 执行存储 ...