zoukankan      html  css  js  c++  java
  • FFT 快速傅里叶变换学习笔记

    FFT 快速傅里叶变换学习笔记

    前言

    由于老吕以及 dsr 巨巨的讲解,将FFT学习了一下可能以后很大几率都用不到,为了防止自己忘了,趁自己还有点记忆总结一下,可能理解的不深,或有错误,请不吝赐教。


    定义

    快速傅里叶变换 (fast Fourier transform), 即利用计算机计算离散傅里叶变换(DFT)的高效、快速计算方法的统称,简称FFT。快速傅里叶变换是1965年由J.W.库利和T.W.图基提出的。采用这种算法能使计算机计算离散傅里叶变换所需要的乘法次数大为减少,特别是被变换的抽样点数N越多,FFT算法计算量的节省就越显著。 ——源自百度百科


    多项式

    FFT主要是用于加速求两个多项式相乘的过程。

    多项式:通俗来讲就是有很多项的式子。

    一个 (n) 项式,形如:

    (f(x)=a_0+a_1x+a_2x^2+a_3x^3+dots + a_nx^n)

    也可以写成

    (f(x)=sumlimits^n_{i=0}a_i imes x^i)

    多项式的表示法

    我们去表示一个多项式,或者说去求解一个多项式,主要有两种方法。

    • 系数表示法

      这是我们平时最常见的表示多项式的方法。就比如说我们上面的栗子。

      如果我们要用系数表示的多项式计算乘积,如 (f(x) imes g(x)) ,想象一下,第一个多项式的每一项都要乘上第二个多项式的每一项,这样的复杂度是 (O(n)) 的。

    • 点值表示法

      一个 (n) 次的多项式,可以由 (n) 个点确定。比如说 (y(x)=a_0+a_1x+a_2x^2+a_3x^3+dots + a_nx^n),就可以由 (n) 个点来表示,分别为 ((x_1,y_1),(x_2,y_2),(x_3,y_3),dots,(x_n,y_n))​ 。

      这样我们计算 (f(x) imes g(x)) 也是 (O(n)) 的。

      (f(x),g(x)) 中选出我们要求的 (n)​ 个点(也就是我们每次带入一个 (x_i),用给出的函数求出 (y_i)),然后求出对应的乘积,也就是在相乘函数中对应的值,这样做的复杂度是 (O(n))​ 的。但是一般题目可能会让我们输出系数表示法,所以我们需要将点值表示法转成系数表示法,但是点值表示法转换成系数

      (O(n^2))​ 的,所以说复杂度还是 (O(n^2))​ 的。

    系数表示法的复杂度不好优化,而点值表示法是 (O(n))​ 的,所以我们考虑去优化转化的过程。


    复数

    一些定义

    以下为数学范围内的知识,学过的可跳过。

    我们定义 (i) 为虚数单位, (i^2=-1)

    初中的时候,解方程我我们总是说在实数范围内有解或无解。

    例如:(x^2+2x+3=0)

    对于这种方程,我们总是说在实数范围内无解,而在复数范围内,这个方程式有解的。

    [egin{align*} &x^2+2x+3 =0\ &x^2+2x=-3\ &x^2+2x=3i^2 \ &(x+1)^2=3i^2+1\ & herefore x=-1pm sqrt{3i^2+1} end{align*} ]

    我们把形如 (a+bi)​ 的数叫复数,其中 (a,bin R)(实数)。​

    在复平面中,(x)​​​​​ 轴代表实数,(y)​​​​ 轴代表虚数,从原点到 ((a,b))​​ 向量表示复数 (a+bi)​。

    我们在复平面内,将复数对应到向量上,向量与 x 轴正半轴的夹角为 (alpha)​ ,此时复数可以表示为

    (r(cosalpha+isinalpha))

    复数的三角形式

    模长:从原点到 ((a,b)) 的距离,(sqrt{(a-0)^2+(b-0)^2})

    幅角:以逆时针为正方向,从 (x)​ 轴正半轴到已知向量的转角的有向角叫做幅角。

    运算法则

    大致了解一下运算规律就行。

    ((a+bi) + (c+di) = (a+c)+(b+d)i)​​

    ((a+bi) - (c+di)=(a-c)+(b-d)i) (加法的逆运算)

    代数式:

    [egin{align*} (a+bi) imes(c+di) &=ac+adi+bci+bdi^2\ &=ac+bdi^2+(ad+bc)i\ &=ac-bd+(ad+bc)i end{align*} ]

    三角形式:

    [egin{align*} large &r_1(cos heta_1+isin heta_1) imes r_2(cos heta_2+isin heta_2) \ large &=r_1 imes r_2(cos heta_1cos heta_2+icos heta_1sin heta_2+isin heta_1cos heta_2+i^2sin heta_1sin heta_2) \ large &=r_1 imes r_2((cos heta_1cos heta_2-sin heta_1sin heta_2)+i(cos heta_1sin heta_2+sin heta_1cos heta_2)) \ large &=r_1 imes r_2(cos( heta_1+ heta_2)+isin( heta_1+ heta_2)) end{align*} ]

    也就是模长相乘,幅角相加。这里比较重要。

    代数式:

    [egin{align*} frac{a+bi}{c+d_i} &=frac{(a+bi)(c-di)}{(c+di)(c-di)} \ &=frac{ac+bd-(ad+bc)i}{c+d} end{align*} ]

    三角形式:

    [egin{align*} &frac{r_1(cos heta_1+isin heta_1)}{r_2(cos heta_2+isin heta_2)} =frac{r_1}{r_2} imes(cos( heta_1- heta_2)+isin( heta_1- heta_2))\ end{align*} ]

    虽然FFT中不用复数除法。

    单位根

    定义

    在单位圆中,以圆点为起点,圆的 (n)​​​​ 等分点为终点,做 (n)​ 个向量,设幅角为正且最小的向量对应的复数为(omega_n)​,称为 (n)​​​ 次 单位根

    (omega_n^k) 表示 (k)(omega_n) 。易得,(omega_n^n=omega_n^0=1)(omega_n^{frac{1}{2}}=-1)(n) 为偶数)。

    性质

    1. 欧拉公式:

      (e^{ix} = cos(x)+i imes sin(x))

      带入

      (omega_n^k = cos(k imesfrac{2pi}{n})+i imes sin(k imesfrac{2pi}{n}))

    2. (omega _{2n}^{2k}=omega _{n}^{k})

    3. (omega _{n}^{k+frac{n}{2}}=-omega _{n}^{k})

    4. ((omega_n^k)^2=omega_n^{2k})

    5. (omega_n^{k+n}=omega_n^k)


    FFT

    考虑一个多项式 (A(x)) 求它的 DFT

    [egin{align*} A(x) &=a_0+a_1x+a_2x^2+a_3x^3+a_ax^4+dots+a_nx^n\ &=(a_0+a_2x^2+a_4x^4+dots)+(a_1x+a_3x^3+a_5x^5dots) \ &=(a_0+a_2x^2+a_4x^4+dots)+x(a_1+a_3x^2+a_3x^5dots) \ ext{令} a_1(x)&=(a_0+a_2x...) , a_2(x)=(a_1+a_3x...)\ \ A(x)&=a_1(x^2)+xa_2(x^2) end{align*} ]

    (kleq frac{n}{2})

    [egin{align*} A(omega_n^k) &=a_1((omega_n^k)^2)+omega_n^ka_2((omega_n^k)^2) \ &=a_1(omega_n^{2k})+omega_n^ka_2(omega_n^{2k})\ &=a_1(omega_frac{n}{2}^k)+omega_n^ka_2(omega_frac{n}{2}^k) end{align*} ]

    (k> frac{n}{2})

    [egin{align*} A(omega_n^{k+frac{n}{2}}) &=a_1((omega_n^{k+frac{n}{2}})^2)+omega_n^{k+frac{n}{2}}a_2((omega_n^{k+frac{n}{2}})^2) \ &=a_1(omega_n^{2k+n})+omega_n^{k+frac{n}{2}}a_2(omega_n^{2k+n}) \ &=a_1(omega_n^{2k})+omega_n^{k+frac{n}{2}}a_2(omega_n^{2k}) \ &=a_1(omega_frac{n}{2}^k)+omega_n^{k+frac{n}{2}}a_2(omega_frac{n}{2}^k) \ &=a_1(omega_frac{n}{2}^k)-omega_n^ka_2(omega_frac{n}{2}^k) end{align*} ]

    我们发现,当 (k>frac{n}{2}) 的时候,与 (kleq frac{n}{2}) 的时候就相差了一个符号,当我们求出 (kleq frac{n}{2}) 中的数值时,就可以推出 (k>frac{n}{2}) 的值,因此我们只用计算 (kleqfrac{n}{2}) 的时候就可以了。

    看图可以看出我们每次都是一个递归的过程,然后进行大眼观察法,观察我们递归后的东西。

    变化前 0 1 2 3 4 5 6 7
    000 001 010 011 100 101 110 111
    变化后 0 4 2 6 1 5 3 7
    000 100 010 110 001 101 011 111

    剩下的先咕了,以后再补,图好像也挂了

    本欲起身离红尘,奈何影子落人间。
  • 相关阅读:
    设计模式:Prototype 原型模式
    [C++STDlib基础]关于单字符的操作——C++标准库头文件<cctype>
    Android开发之简单的电子相册实现
    autotools入门笔记(二)——创建和使用静态库、动态库
    Dreamer 框架 比Struts2 更加灵活
    Redis集群明细文档
    【Servlet3.0新特性】第03节_文件上传
    POJ 3264 Balanced Lineup
    利用jquery对ajax操作,详解原理(附代码)
    C语言实现修改文本文件中的特定行
  • 原文地址:https://www.cnblogs.com/jcgf/p/15059818.html
Copyright © 2011-2022 走看看