今天完成了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; }
浙公网安备 33010602011771号