快速傅里叶(FFT)

快速傅里叶:

更加形象的理解傅里叶变换:http://zhuanlan.zhihu.com/wille/19763358

大概了解之后:https://www.zhihu.com/question/19714540?rf=20254033

从傅里叶级数到傅里叶变换:


(照片太大,只能裁剪为两张)

刨根问底的同学:https://www.zhihu.com/question/21665935



雷德算法:


输出序列是按自然顺序排列的,而输入序列的顺序则是“比特反转”方式排列的。也就是说,将序号用二进制表示,然后将二进制数以相反方向排列,再以这个数作为序号。如011变成110,那么第3个输入值和第六个输入值就要交换位置了。

详见http://blog.csdn.net/axiqia/article/details/50830435



思路:

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define PI 3.1415926   //定义圆周率值
#define N  16 //变换点数

using namespace std;

typedef struct compx
{
    float real;
    float img;
}compx;


//复数乘法
compx Multi(compx a, compx b)
{
    compx c;
    c.real = a.real*b.real - a.img*b.img;
    c.img = a.real*b.img + a.img*b.real;
    return c;
}
//复数加法
compx Add(compx a, compx b)
{
    compx c;
    c.real = a.real + b.real;
    c.img = a.img + b.img;
    return c;
}
//复数减法
compx Sub(compx a, compx b)
{
    compx c;
    c.real = a.real - b.real;
    c.img = a.img - b.img;
    return c;
}

//快速傅里叶
void FFT(compx data[])
{
    int k, i, j = 0;
    compx u, w, t;
    //自然顺序变成倒位序

    for(i = 0; i < N-1; i++)
    {
        if(i < j)
        {
            t.real = data[i].real;
            t.img = data[i].img;
            data[i].real = data[j].real;
            data[i].img = data[j].img;
            data[j].real = t.real;
            data[j].img = t.img;
        }
        k = N/2;

        //实现进位
        while(k <= j)   //左边最高位为1
        {
            j = j-k;    //最高位1变为0
            k /= 2;
        }
        j += k;

    }

    //计算蝶形级数m
    int f = N, m;
    for(m = 1; (f=f/2) != 1; m++);


    //控制级数
    for(int n = 1; n <= m; n++)
    {
        int a = 2<<(n-1);      //相邻蝶形结的距离.2的n次方
        int b = a/2;          //相邻运算点的距离
        //printf("a = %d b = %d\n", a,b);
        u.real = 1.0;       //蝶形运算的系数
        u.img = 0.0;
        w.real = cos(PI/b);//当前系数与上一系数的商
        w.img = -sin(PI/b);

        int x1, x2;     //参加蝶形运算的两个节点
        for(j = 0; j < b; j++)
        {
            //printf("b = %d\t%lf\t%lf\n",b, u.real, u.img);
            for(x1 = j; x1 < N; x1 += a)
            {
                x2 = x1 + b;

                t = Multi(data[x2], u);
                data[x2] = Sub(data[x1], t);
                data[x1] = Add(data[x1], t);
                //printf("x1 = %d, x2 = %d\n", x1, x2);
            }
            u = Multi(u, w);
        }
    }

}
int main()
{
    compx data[N];
    for(int i = 0; i < N; i++)
    {
        data[i].real = i;
        data[i].img = 0;
    }

    FFT(data);
    for(int i = 0; i < N; i++)
        printf("%lf \t%lf\n", data[i].real, data[i].img);

    return 0;
}



运行结果:


MATLAB对比结果:



  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值