您的位置:首页 > 其它

FFT算法学习

2016-04-15 10:17 183 查看

写在前面:

初学FFT算法移步:here

讲的真心不错,本文主要记录下自己的理解。

建议阅读的过程中,自己动手算一算需要仔细理解的地方!

overview

定义一个多项式:A(x)=Σj=0n−1aj⋅xj

计算 C(x)=A(x)∗B(x)

一般我们要计算两个 n 次多项式的乘积,直接计算的复杂度是 O(n2),利用 FFT 算法可以达到 O(nlogn) 的复杂度,其中利用到了傅里叶变换,周期性,还有分治策略。

大致的思路呢,就是先得到 A(x) 与 B(x) 的点表示法(具体见下文),也就是利用 DFT 算法在O(nlogn) 时间内得到点表示法,然后得到的两个点表示形式在对应位上直接相乘得到 C(x) 的点表示形式,最后就是逆 DFT 得到 C(x) 的多项式表示。

detail

一般我们将多项式表示为 A(x)=a0+a1x+a2x2+...+an−1xn−1,记为:a=(a1,a2,...an−1)

实际上还有另外一种方法来唯一的表征一个多项式 ,即点值法,也就是找出多项式在n 个不同的点上的取值,记为:{(x0,y0),(x1,y1),...,(xn−1,yn−1)},具体证明略。

现在我们的目的是得到 A(x) 的点值表示,直接代入 n 个数,计算的时间复杂度为 O(n2),所以现在就用到了 傅里叶变换 去优化这个过程。

我们选用n个特殊的值,用处后面自然会感受到:

ω0n,ω1n,...,ωn−1n,其中ωn=e2iπn

你会发现上面的取值 ωin 的周期是 n,也就是 i=n+k 与 i=k 时候的值是一样的。

现在我们对 A(x) 作一些变换:

A(x)=A[0](x2)+xA[1](x2)

A[0](x)=a0+a2x+a4x2+...+an−2xn2−1

A[1](x)=a1+a3x1+a5x2+...+an−1xn2−1

现在我们需要分别去计算 A[0](x),A[1](x) 在 上述n 个数上的取值,即计算 (ωin)2,你会发现这个式子的周期是 n/2,所以这个 n 个数的序列的 前后半段完全相同 (聪明的你是否想到了优化的地方呢)!

也就是我们计算A[0](x),A[1](x) 的时候,其实只需代入计算 前n/2 个数,这样问题的规模就缩小了一半,假设我们得到了上述两者的取值结果: v0,v1,...vn/2 和 t0,t1,...tn/2

为什么取负号?自己想一想!(^_^

最后就是递归的计算下去,但是每次计算问题的规模都会为上一次的一半,所以整体的复杂度变为 nlogn

接下来就是逆 DFT:

其实逆DFT与DFT的计算过程类似,只需看看我们之前计算 yi 序列的过程:



那么我们只需要在等式两边分别左乘一个逆矩阵就OK了,如何求上面那个矩阵的逆矩阵呢?

直接给出了矩阵的: C(j,k)=ω−kjnn

具体证明略。

所以要计算 ai 序列,就是一个类似的过程,用逆矩阵去乘我们先前得到的 yi 序列,方法类似嘛,只不过:aj=1nΣk=0n−1ykω−kjn

把之前的 w 替换为 w−1 ,最后除以 n 就完成啦!复杂度也是 nlogn。

all

有错误的话,欢迎指出哦!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  fft 算法