1、FFT算法概要:

FFT(Fast Fourier Transformation)是离散傅氏变换(DFT)的快速算法。即为快速傅氏变换。它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。

2、FFT算法原理:

离散傅里叶变换DFT公式:

FFT算法(Butterfly算法)

设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+(N^2)/2。继续上面的例子,N=1024时,总的运算次数就变成了525312次,节省了大约50%的运算量。而如果我们将这种“一分为二”的思想不断进行下去,直到分成两两一组的DFT运算单元,那么N点的DFT变换就只需要N/2log2N次的运算,N在1024点时,运算量仅有5120次,是先前的直接算法的近1/200,点数越多,运算量的节约就越大,这就是FFT的优越性。

3、FFT算法官方实现:

       

搭建FFTW库并生成所需要的lib文件:

Step1:从官网下载对应的.zip文件,例如我是win10_x86的操作系统,下载64bit的安装包:

Step2:下载完成之后解压到你希望安装的FFTW库的位置

Step3:打开CMD命令操作行,切换到Step2中的安装目录下,执行下面的指令代码生成.lib文件(需要安装Visual Studio,用VC++中的lib命令生成系统能够使用的.lib文件)

打开的方式为,按下window键,输入vs,小娜会自动帮你查找对应的File。

切换到对应的路径之后就可以使用lib命令来生成.lib文件了:

 lib /def:libfftw3-.def
lib /def:libfftw3f-.def
lib /def:libfftw3l-.def

查看对应的目录,我们就能看到生成的.lib文件:

在工程中使用FFTW库

首先在VS2017中创建一个工程命名为FFTW_Test

FFTW_Test.cpp文件内容如下:

 #include <stdio.h>
#include <iostream> #include "fftw3.h"
#pragma comment(lib, "libfftw3-3.lib") using namespace std; int main(void)
{
/*
*fftw_complex 是FFTW自定义的复数类
*引入<complex>则会使用STL的复数类
*/
fftw_complex x[];
fftw_complex y[]; for (int i = ; i < ; i++) {
x[i][REAL] = i;
x[i][IMAG] = ;
} //定义plan,包含序列长度、输入序列、输出序列、变换方向、变换模式
fftw_plan plan = fftw_plan_dft_1d(, x, y, FFTW_FORWARD, FFTW_ESTIMATE); //对于每个plan,应当"一次定义 多次使用",同一plan的运算速度极快
fftw_execute(plan); for (int i = ; i < ; i++) {
cout << y[i][REAL] << " " << y[i][IMAG] << endl;
} //销毁plan
fftw_destroy_plan(plan);
}

将FFTW相关的库文件拷贝到FFTW_Test工程目录下,拷贝的位置需要和FFTW_Test.cpp在同一个目录当中!

拷贝的文件如下图所示(只需要将FFTW安装目录下的这三个文件拷贝过去即可):

程序运行结果:

参考资料

4、FFT算法C/C++/Python代码:

Code1(DFT):

 char DFT_Alg(float *Signal, float *Fre, int L)
{
long long i,j;
float real, imag, coff1, coff2;
coff1 = -*pi/L;
for(i=;i<L;i++){
for(j=;j<L;j++){
coff2 = coff1*i*j;
real += Signal[j]*cos(coff2);
imag += Signal[j]*sin(coff2);
}
printf("Processing:%d\n",i);
Fre[i] = real*real + imag*imag;
}
return ;
}

Code2(FFT):

 typedef float FFT_TYPE;

 #ifndef PI
#define PI (3.14159265f)
#endif typedef struct complex_st {
FFT_TYPE real;
FFT_TYPE img;
} complex; static void BitReverse(complex *x, complex *r, int n, int l)
{
int i = ;
int j = ;
short stk = ;
static complex *temp = ; temp = (complex *)malloc(sizeof(complex) * n);
if (!temp) {
return;
} for(i=; i<n; i++) {
stk = ;
j = ;
do {
stk |= (i>>(j++)) & 0x01;
if(j<l)
{
stk <<= ;
}
}while(j<l); if(stk < n) { /* 满足倒位序输出 */
temp[stk] = x[i];
}
}
/* copy @temp to @r */
for (i=; i<n; i++) {
r[i] = temp[i];
}
free(temp);
} int fft(complex *x, int N)
{
int i,j,l,ip;
static int M = ;
static int le,le2;
static FFT_TYPE sR,sI,tR,tI,uR,uI; M = (int)(log(N) / log()); BitReverse(x,x,N,M); for (l=; l<=M; l++) {
le = (int)pow(,l);
le2 = (int)(le / );
uR = ;
uI = ;
sR = cos(PI / le2);
sI = -sin(PI / le2);
for (j=; j<=le2; j++) {
//jm1 = j - 1;
for (i=j-; i<=N-; i+=le) {
ip = i + le2;
tR = x[ip].real * uR - x[ip].img * uI;
tI = x[ip].real * uI + x[ip].img * uR;
x[ip].real = x[i].real - tR;
x[ip].img = x[i].img - tI;
x[i].real += tR;
x[i].img += tI;
}
tR = uR;
uR = tR * sR - uI * sI;
uI = tR * sI + uI *sR;
}
}
return ;
}
int ifft(complex *x, int N)
{
int k = ;
for (k=; k<=N-; k++) {
x[k].img = -x[k].img;
}
fft(x, N); /* using FFT */
for (k=; k<=N-; k++) {
x[k].real = x[k].real / N;
x[k].img = -x[k].img / N;
}
return ;
}

Code3(DFT-Python):

 def DFT(x):
"""
Input:
x (numpy array) = input sequence of length N
Output:
The function should return a numpy array of length N
X (numpy array) = The N point DFT of the input sequence x
"""
N = len(x)
real = np.zeros(N)
imag = np.zeros(N)
for i in range(N):
for j in range(N):
real[i] += x[j]*np.cos(-2*np.pi*i*j/N)
imag[i] += x[j]*np.sin(-2*np.pi*i*j/N)
Res = 1j*imag + real
return Res
def IDFT(X):
"""
Input:
X (numpy array) = frequency spectrum (length N)
Output:
The function should return a numpy array of length N
x (numpy array) = The N point IDFT of the frequency spectrum X
"""
N = len(X)
real = np.zeros(N)
imag = np.zeros(N)
for i in range(N):
for k in range(N):
param1 = X[k].real
param2 = X[k].imag
sin = np.sin(2*np.pi*i*k/N)
cos = np.cos(2*np.pi*i*k/N)
real[i] += param1*cos-param2*sin
imag[i] += param1*sin+param2*cos
Res = 1j*imag/N + real/N
return Res

5、多种平台的FFT算法移植:

未完待续

FFT快速傅里叶变换算法的更多相关文章

  1. CQOI2018 九连环 打表找规律 fft快速傅里叶变换

    题面: CQOI2018九连环 分析: 个人认为这道题没有什么价值,纯粹是为了考算法而考算法. 对于小数据我们可以直接爆搜打表,打表出来我们可以观察规律. f[1~10]: 1 2 5 10 21 4 ...

  2. FFT 快速傅里叶变换 学习笔记

    FFT 快速傅里叶变换 前言 lmc,ikka,attack等众多大佬都没教会的我终于要自己填坑了. 又是机房里最后一个学fft的人 早背过圆周率50位填坑了 用处 多项式乘法 卷积 \(g(x)=a ...

  3. 「学习笔记」FFT 快速傅里叶变换

    目录 「学习笔记」FFT 快速傅里叶变换 啥是 FFT 呀?它可以干什么? 必备芝士 点值表示 复数 傅立叶正变换 傅里叶逆变换 FFT 的代码实现 还会有的 NTT 和三模数 NTT... 「学习笔 ...

  4. matlab中fft快速傅里叶变换

    视频来源:https://www.bilibili.com/video/av51932171?t=628. 博文来源:https://ww2.mathworks.cn/help/matlab/ref/ ...

  5. FFT(快速傅立叶算法 for java)

    package com.test.test2; public class FFT {     public static final int FFT_N_LOG = 10; // FFT_N_LOG ...

  6. FFT —— 快速傅里叶变换

    问题: 已知A[], B[], 求C[],使: 定义C是A,B的卷积,例如多项式乘法等. 朴素做法是按照定义枚举i和j,但这样时间复杂度是O(n2). 能不能使时间复杂度降下来呢? 点值表示法: 我们 ...

  7. [C++] 频谱图中 FFT快速傅里叶变换C++实现

    在项目中,需要画波形频谱图,因此进行查找,不是很懂相关知识,下列代码主要是针对这篇文章. http://blog.csdn.net/xcgspring/article/details/4749075 ...

  8. FFT快速傅里叶变换

    FFT太玄幻了,不过我要先膜拜HQM,实在太强了 1.多项式 1)多项式的定义 在数学中,由若干个单项式相加组成的代数式叫做多项式.多项式中的每个单项式叫做多项式的项,这些单项式中的最高项次数,就是这 ...

  9. FFT(快速傅里叶变换)

    学习了FFT用来求多项式的乘法,看了算导上的介绍,上面讲的非常明白,概括一下FFT的原理就是,我们在计算多项式的乘法时,如果暴力模拟的话是n^2 复杂度的,就像小学学的竖式乘法一样,比如一个n位数乘上 ...

随机推荐

  1. Python的优势及应用领域

    Python的优势 Python是一门解释型语言,是比较容易入门. Python的程序代码更接近英语,更好好理解. Python的扩展库非常丰富. Python与C的粘合性非常好. Python的缺点 ...

  2. python--协程之特别篇

    Python通过yield提供了对协程的基本支持,但是不完全.而第三方的gevent为Python提供了比较完善的协程支持. gevent是第三方库,通过greenlet实现协程,其基本思想是: 当一 ...

  3. [C#] .NET4.0中使用4.5中的 async/await 功能实现异步

    在.NET Framework 4.5中添加了新的异步操作库,但是在.NET Framework 4.0中却无法使用.这时不免面临着抉择,到底是升级整个解决方案还是不使用呢? 如果你的软件还没发布出去 ...

  4. git体验

    (1)git初始化配置#配置用户名git config --global user.name "azcode"#配置邮箱git config --global user.email ...

  5. CentOS命令登录MySQL时,报错ERROR 1045 (28000): Access denied for user root@localhost (using password: NO)错误解决方法

    1.停用mysql服务:# /etc/rc.d/init.d/mysqld stop 2.输入命令:# mysqld_safe --user=mysql --skip-grant-tables --s ...

  6. mysql并发控制之快照读和当前读

    上一篇简单的介绍了下MVCC(多版本并发控制)的原理,MVCC会对事物内操作的数据做多版本控制,从而实现并发环境下事物对数据写操作的阻塞不影响读操作的性能.而这个多版本控制的实现是由undo log来 ...

  7. C语言通讯录系统——C语言单向链表实现

    实现的通讯录功能有:查看通讯录.添加联系人.删除联系人.查询联系人.保存并退出. 通过txt文件保存和读取通讯录数据. #include <stdio.h> #include <st ...

  8. 补记:完成了NG的SP1的全部内容 开始第二周

    DL本质上就是多层的Logistics Regression with different activation function and nicely designed back propagati ...

  9. 2018-2019-2 20165231王杨鸿永《网络对抗》Exp1 PC平台逆向破解

    实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串. 该程序同时包含另一个代码片段,getShe ...

  10. django+vue

    django安装配置方式略过 1.安装node.js,官网地址:https://nodejs.org/zh-cn/download/ 2.cd到项目目录下,执行npm install -g vue-c ...