FFT——快速傅里叶变换
- insorker
- 2021/4/12
有个同学问我,说一个英国大力士,左手一个多项式,右手一个多项式,把它们乘起来要花多少时间?
他说他用死劲算,是 O(n2)
我说停停,中国武功讲究化劲,两个不等式相乘 O(nlogn) 就可以解决了
他说真的吗,我不。。。
我没等他说完,啪的一下,很快啊
一个FFT,一个IDFT
百度了一天,终于解决了
笔记
我的学习路线是先看了DFT,然后发现看不看都可以
那个主要提供的是对信号频率分离的思想和方法
如果不看的话,你可能不知道我要算多项式乘法有什么用
简单解释一下计算机是不知道信号的输入是什么样的,周期几何?幅值多少?
人眼可以很方便的看到的东西计算机也未必看得到,更何况多种信号叠加在一起呢
所以 DFT 通过对 cos (算幅度) sin (算相位),两个分量进行离散傅里叶变换(不就是e的复指数幂嘛)
先离散取点,得到原来的波形的一堆点(注意点值这个要素已经来了)
然后暴力取点所有(我也不知道怎么描述)不同周期(两个周期内,再多了就重复了,因为ein是周期函数)的信号,与原来的那一堆点对应相乘(多项式相乘)
众所周知(我数学不好,没看过怎么证明)sin、cos有正交性,很多项算出来都是 0
不是 0 的就是分离出来的量了
DFT
采样频率 fs :单位时间内采集多少个点
采样周期 Ts :采样频率的倒数,采集一个点需要多少时间
如果我采集了N个点,那么就花了 N * Ts 的时间
如果这段时间内原信号出现了 k 个周期
那么原信号的周期就是 N * Ts / k ,同理频率就是 k / (N * Ts) = k * fs / N
而 FFT 是对 DFT 的快速计算
代码
// 为什么用C写,好问题,为了能在只能用C的地方用
#include <iostream>
#include <math.h>
#define pi acos(-1)
const int N = 100010;
int f[N], g[N];
int l = 1, k = 0, r[10] = {
};
struct ZComplex {
double real;
double imag;
};
ZComplex ZComplex_Add(const ZComplex* a, const ZComplex* b) {
return