gfxenon

导航

 

今天完成了FFT的代码,复数部分使用了上次写的复数类。

核心代码还是很简单,只有寥寥几行。

理解FFT这个计算,最重要的是理解复数,通过复平面的概念可以比较快的理解FFT的推导。

想起大学时候在复变科上学习复平面,不是很明白这么做到底有什么意义。借助于之前高数的基础,虽然这门课学的比较轻松。

但是回头想起来它的精髓并没有领会到。导致现在一碰复数就有点发怵。

其实这也是思想上懒惰的体现之一。

遇到什么新的知识,总是想办法转换到自己最熟悉的领域,一直用旧的思想去理解新的领域。越来越固守在自己的思维当中。

其实一个进入一个新的领域,最重要的是学习它独有的思想。

如果先转换到旧的思想下,刚开始可能上手比较快,但是会发现越到后面越寸步难行。

每次接触新的学科,都应该潜心思考,发现它内在的逻辑,记住一些基本的理论基础,按照它本身的逻辑去推演。这样才是面对新知识的方法和态度。

回到FFT或者写代码这件事上来,写代码的核心是不断积累。

计算机几门基础课程都没有很深的理论基础,而且往往推导公式很复杂,最后代码缺很简单。

那么理解这些东西就应该从实际编码入手。如果自己从底层开始写,每一步都应该思考后面很多步,思考怎么把它变成完善而且使用起来很便利的一组东西。

如果使用高级语言,调用别人API为主,就应该多思考每个API都有多少种用法,怎么样组合是最优的。

FFT和复数这两个东西还应该继续打磨,继续优化。

python和爬虫则应该多多查文档,思考怎么调用别人的库是对自己最有利的。代码可读性是最强的。

同时最重要的是多试验,多动手。这样才能不断提升。

#include <iostream>
#include "MyComplex.h"
#include <vector>
using namespace std;
using namespace MyComplex;



vector<mycomplex> myfft(const vector<double>& a, int n)
{
    vector<mycomplex> ret;
    if (n==1)
    {
        ret.push_back(mycomplex(a[0], 0));
        return ret;
    }
    vector<double> ao, ae;
    for (int i = 0; i < n; i += 2)
    {
        ae.push_back(a[i]);
    }
    for (int i = 1; i < n; i += 2)
    {
        ao.push_back(a[i]);
    }
    vector<mycomplex> aex, aox;
    aex = myfft(ae, n / 2);
    aox = myfft(ao, n / 2);
    ret.resize(n);
    mycomplex w(1, 0);
    for (int i = 0; i < n / 2; i++)
    {
        ret[i] = aex[i] + w * aox[i];
        ret[i + n / 2] = aex[i] - w * aox[i];
        w.theta += 2 * PI / n;
    }
    return ret;
}

void ffttest(void)
{
    vector<double> a;
    for (int i = 0; i < 16; i++)
    {
        a.push_back(i + 1);
    }
    vector<mycomplex> ac;
    ac = myfft(a, 16);
    for (int i = 0; i < 16; i++)
    {
        cout << mycomplex(1, PI / 16 * i) << " " << ac[i] << endl;
    }
}


int main()
{
    ffttest();
    system("pause");
    return 0;
}

 

posted on 2017-12-06 22:03  gfxenon  阅读(388)  评论(0)    收藏  举报