基4快速傅里叶变换
一、功能
计算复序列的基4快速傅里叶变换。
二、方法简介
序列\(x(n)(n=0,1,...,N-1)\)的离散傅里叶变换定义为
\[
X(k)=\sum_{n=0}^{N-1}x(n)W_{N}^{nk}, \qquad k=0,1,...,N-11
\]
其中\(W_{N}^{nk}=e^{-j\frac{2\pi nk}{N}}\),若\(N=4^M\),则将序列\(x(n)\)分成四个\(N/4\)点的序列\(x_1(n) 、x_2(n) 、x_3(n) 、x_4(i)(n=0,1, …,N/4—1)\), 即
\[
x(n) =x_1(n) +x_2(n) +x_3(n) +x_4(n)
\]
式中
\[
\left\{\begin{matrix}\begin{align*}x_{1}(n)&=x(n), & (n=0,1,...,N /4 - 1)\\ x_{2}(n)&=x(n+\frac{N}{4}), & (n=0,1,...,N /4 - 1)\\ x_{3}(n)&=x(n+\frac{N}{2}), & (n=0,1,...,N /4 - 1)\\ x_{4}(n)&=x(n+\frac{3N}{4}), & (n=0,1,...,N /4 - 1)\end{align*}\end{matrix}\right.
\]
把\(x(n)\)代入DFT表达式中,则有
\[
\begin{align*}X(k)&=\sum_{n=0}^{N/4-1}[x_{1}(n)W_{N}^{nk}+x_{2}(n)W_{N}^{(n + N/4)k}+x_{3}(n)W_{N}^{(n + N/2)k}+x_{4}(n)W_{N}^{(n + 3N/4)k}]\\&=\sum_{n=0}^{N/4-1}[x_{1}(n)+x_{2}(n)W_{N}^{N/4k}+x_{3}(n)W_{N}^{N/2k}+x_{4}(n)W_{N}^{3N/4k}]W_{N}^{nk}\\\end{align*}\\(k=0,1,...,N-1)
\]
把\(X(k)\)按频率抽取,得
\[
\left\{\begin{matrix}\begin{align*}X(4k)&=\sum_{n=0}^{N/4-1}[x_{1}(n)+x_{2}(n)+x_{3}(n)+x_{4}(n)]W_{N/4}^{nk}\\X(4k+1)&=\sum_{n=0}^{N/4-1}[x_{1}(n)-jx_{2}(n)-x_{3}(n)+jx_{4}(n)]W_{N}^{n}W_{N/4}^{nk}\\X(4k+2)&=\sum_{n=0}^{N/4-1}[x_{1}(n)-x_{2}(n)+x_{3}(n)-x_{4}(n)]W_{N}^{2n}W_{N/4}^{nk}\\X(4k+3)&=\sum_{n=0}^{N/4-1}[x_{1}(n)+jx_{2}(n)-x_{3}(n)-jx_{4}(n)]W_{N}^{3n}W_{N/4}^{nk}\end{align*}\end{matrix}\right.
\]
通过上面得分解,可求得所有\(X(k)\)值,其基本运算式为
\[
\left\{\begin{matrix}\begin{align*}f_{1}(n)&=x_{1}(n)+x_{2}(n)+x_{3}(n)+x_{4}(n)\\f_{2}(n)&=[x_{1}(n)-jx_{2}(n)-x_{3}(n)+jx_{4}(n)]W_{N}^{n}\\f_{3}(n)&=[x_{1}(n)-x_{2}(n)+x_{3}(n)-x_{4}(n)]W_{N}^{2n}\\f_{4}(n)&=[x_{1}(n)+jx_{2}(n)-x_{3}(n)-jx_{4}(n)]W_{N}^{3n}\end{align*}\end{matrix}\right.,(k=0,1,...,\frac{N}{4}-1)
\]
这样,就将一个\(N\)点得DFT转化为四个\(N/4\)点DFT来计算。依此类推,直至分解到最后一级。以上就是按频率抽取的基4快速傅里叶变换算法。与基2FFT相比,基4FFT的乘法量约减少25%,加法量也略有减少。
三、使用说明
是用C语言实现基4快速傅里叶变换(FFT)的方法如下:
/************************************
x ---一维数组,长度为n,开始时存放要变换数据的实部,最后存放变换结果的实部。
y ---一维数组,长度为n,开始时存放要变换数据的虚部,最后存放变换结果的虚部。
n ---数据长度,必须是4的整数次幂。
************************************/
#include "math.h"
void fft(double *x, double *y, int n)
{
int i, j, k, m, il, i2, i3, nl, n2;
double a, b ,c ,e ,rl ,r2 ,r3 ,r4 ,s1 ,s2 ,s3 ,s4;
double col, co2, co3, sil, si2, si3;
for(j = 1; i = 1; i < 10; i++) {
m = i;
j = 4 * j;
if(j == n) break;
}
n2 = n;
for(k = 1; k <= m; k++) {
n1 = n2;
n2 = n2 / 4;
e = 6.28318530718 / nl;
a = 0;
for(j = 0; j < n2; j++) {
b = a + a;
c = a + b;
co1 = cos(a);
co2 = cos(b);
co3 = cos(c);
sil = sin(a);
si2 = sin(b);
si3 = sin(c);
a = (j + l) * e;
for(i = j; i < n; i = i +n1) {
il = i + n2;
i2=il+n2;
i3 = i2 + n2;
nl = n-1;
r1 = x[i] + x[i2];
r3 = x[i] - x[i2];
s1 = y[i] + y[i2];
s3 = y[i] - y[i2];
r2 = x[il] + x[i3];
r4 = x[il] — x[i3];
s2 = y[il] + y[i3];
s4 = y[il] - y[i3];
x[i] = rl — r2;
r2 = r1 — r2;
rl = r3 — s4;
r3 = r3 + s4;
y[i] = s1 + s2;
s2 = s1 - s2;
s1 = s3 + r4;
s3 = s3 — r4;
x[il] = col * r3 + sil * s3;
y[il] = col* s3 — sil * r3;
x[i2] = co2 * r2 + si2 * s2;
y[i2] = co2 * s2 — si2 * r2;
x[i3] = co3 * rl + si3 * s1;
y[i3] = co3 * s1 — si3 * r1;
}
}
}
n1 = n - 1;
for(j = 0, i = 0; i < n1; i++) {
if(i < j) {
rl = x[j];
s1 = y[j];
x[j] = x[i];
y[j] = y[i];
x[i] = rl;
y[i] = sl;
}
k = n / 4;
while( 3 * k < (j + 1)) {
j = j - 3 * k;
k = k / 4;
}
j = j + k;
}
}
原文地址:https://www.cnblogs.com/liam-ji/p/11693632.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 详解Ubuntu16.04安装nvidia驱动+CUDA+cuDNN的教程
- linux free命令详解
- Linux下memcache编译安装与基本使用教程
- Linux中MongoDB如何实现远程自动备份详解
- 覆盖原先的PATH导致命令失效提示command not found的解决方法
- Linux中可以节省你时间的15个命令别名
- Linux下利用unzip命令如何解压多个文件详解
- linux查看磁盘使用情况方法
- 详解Linux(centos7)下安装OpenSSL安装图文方法
- 面试官:考你几个简单的事件问题吧
- 如何创建Linux的swap交换分区文件的方法步骤
- Linux利用keepalived实现lvs的高可用性的操作方法
- Canvas系列(11):动画中级
- 使用autoconf生成Makefile并编译工程的步骤
- frida- registernatives获取so层动态注册函数