首页 > 其他分享 >快速傅里叶变换 | FFT 初学

快速傅里叶变换 | FFT 初学

时间:2023-12-13 20:22:22浏览次数:27  
标签:系数 多项式 FFT 初学 点值 quad tfrac 傅里叶

FFT

前置

多项式:形如 \(A(x)=\sum\limits_{i=0}^{n-1}a_ix^i\) 的式子,其中 \(n\) 表示项数

多项式乘法:

\[\begin{aligned}C(x) & = A(x)\cdot B(x) \\ & = \sum\limits_{i=0}^{2n-2}c_ix^i\end{aligned} \]

其中,\(c_i=\sum\limits_{j=0}^ia_jb_{i-j}\)。

多项式表示法:

  • 系数表示法:将每一项的系数拿出来写在一起共同组成一个向量,如果缺项就补 \(0\)。一般书写的顺序与数组下标对应。

\[A(x)=(a_0,a_1,a_2,\cdots,a_{n-1}) \]

  • 点值表示法:任意的 \(n\) 次多项式都可以由二维平面内任意 \(n+1\) 个点唯一确定,因为一个方程可以解出一个系数。故 \(n\) 次多项式可以用一个包含 \(n+1\) 个二维平面内的点集来表示。

\[A(x)=\{(x_0,y_0),(x_1,y_1),(x_2,y_2),\cdots,(x_{n-1},y_{n-1})\} \]

快速傅里叶变换

对两种表示法分别进行多项式乘法,不难发现,系数表示法的过程是基于乘法分配律的,\(O(n^2)\) 的时间复杂度难以优化;而对于点值表示法来说,如果两个多项式分别是 \(n\) 次和 \(m\) 次的,那么最终的多项式是 \(n+m\) 次的,是需要 \(n + m + 1\) 个点来确定的。那么只需要将两个多项式均用 \(n+m+1\) 个点表示,在两两相乘即可得到目标点值,时间复杂度 \(O(n)\)。

但是,一般题目给定了多项式的系数表示,为了快速实现多项式乘法,我们需要快速实现多项式的系数表示转点值表示,这也就是FFT做的事情。

至此,我们大致了解了多项式乘法的基本过程。

  • 求值:将多项式 \(A(x),B(x)\) 通过FFT由系数表示转化成点值表示;
  • 点乘:然后将点值表示下的 \(A(x),B(x)\) 通过 \(O(n)\) 的点乘得到结果 \(C(x)\) 的点值表示;
  • 插值:将多项式 \(C(x)\) 通过FFT的逆操作还原出 \(C(x)\) 的系数表示。

那么,要如何实现求多项式的一个点值呢?这里我们采用霍纳法则将多项式展开。

\[A(x_0)=a_0+x_0(a_1+x_0(a_2+x_0(a_3+\cdots+x_0a_{n-1})\cdots)) \]

那么我们可以在 \(O(n)\) 的时间内求出单次询问定点 \(x_0\) 的 \(A(x_0)\)。

单位根

定义:在复数域下,我们称满足 \(w^n=1\) 的 \(w\) 为 \(n\) 次单位根,记为 \(w_n\)。

由代数基本定理可知,\(n\) 次单位根有 \(n\) 个。以实轴为横轴,虚轴为纵轴建系,以原点为圆心作单位圆,那么这 \(n\) 个 单位复数根均匀分布在以复平面的原点为圆心的单位半径的圆周上,分别为 \(e^{\tfrac{2\pi ik}{n}}\),其中 \(k=0\sim n-1\)。

\(e^{ix}=\cos(x)+i\sin(x)\),借助图像可以更好地理解。

下面给出有关单位根的几则引理。

  • 消去引理:若 \(n,k\ge 0,d> 0\),则有 \(w_{dn}^{dk}=w_n^k\)。

    证明:

    \[w_{dn}^{dk}=(e^{\tfrac{2\pi i}{dn}})^{dk}=(e^{\tfrac{2\pi i}{n}})^k=w_n^k \]

    推论:\(w_n^{\tfrac{n}{2}}=w_2=-1\)
  • 折半引理:若 \(n\) 是大于 \(0\) 的偶数,则 \(n\) 个 \(n\) 次单位复数根的平方的集合就是 \(\dfrac{n}{2}\) 次单位复数根的集合,共 \(\dfrac{n}{2}\)。通俗点说,\(n\) 次单位复数根的前后两半平方后是对应相等的。

    证明:

    \[(w_n^{\tfrac{n}{2}+k})^2=w_n^{n+2k}=w_n^n\cdot w_n^{2k}=(w_n^k)^2 \]

    推论:\(w_n^{\tfrac{n}{2}+k}=-w_n^k\)
  • 求和引理:对于 \(n\ge 1\) 和满足 \(k\nmid n\) 的非负整数 \(k\),有

    \[\sum\limits_{j=0}^{n-1}(w_n^k)^j=0 \]

下面讲讲如何在 \(O(n\log n)\) 的时间内实现求值。

我们将 \(n\) 个 \(n\) 次单位复数根代入前面展开后的多项式求点值。对于 \(k\in [0,n)\),和 \(n-1\) 次的多项式 \(A(x)\),定义

\[y_k=A(w_n^k)=\sum\limits_{i=0}^{n-1}a_i(w_n^k)^i \]

而对于一个多项式 \(A(x)\),我们把奇数下标和偶数下标分别独立出来,定义成 \(2\) 个子多项式。

\[\begin{cases} A^{[0]}(x)=a_0+a_2x+a_4x^2+\cdots+a_{n-2}x^{\tfrac{n}{2}-1} \\ A^{[1]}(x)=a_1+a_3x+a5x^2+\cdots+a_{n-1}x^{\tfrac{n}{2}-1} \end{cases} \]

这样,将 \(A(x)\) 可以表示成 \(A^{[0]}(x^2)+x\cdot A^{[1]}(x^2)\)。

这显然是可以分治递归求解的,每次次数界折半,时间复杂度 \(O(n\log n)\)。

插值的话,就是反过来做,推到一下式子可得:

\[a_k=\dfrac{1}{n}\sum\limits_{i=0}^{n-1}y_i(w_n^{-k})^i \]

发现求系数的过程与前面求点值的过程类似,也可以在 \(O(n\log n)\) 的时间内求解。

优化

  • 蝶形变换

    令 \(n=8\),那么不难发现递归时 \(a\) 长这样。

    \[[0\quad 1\quad 2\quad 3\quad 4\quad 5\quad 6\quad 7] \]

    \[[0\quad 2\quad 4\quad 6]\ [1\quad 3\quad 5\quad 7] \]

    \[[0\quad 4]\ [2\quad 6]\ [1\quad 5]\ [3\quad 7] \]

    \[[0]\ [4]\ [2]\ [6]\ [1]\ [5]\ [3]\ [7] \]

    记最后的数组为 \(a'\),则有 \(a'_i=a_{rev(i)}\),故一开始时可以交换 \(a_i\) 和 \(a_{rev(i)}\) 以减少常数。

  • 三次变两次

    发现整个过程先要求两个多项式 \(A(x),B(x)\) 的点值,点乘后又要还原出系数,总共进行了 \(3\) 次FFT。

    把 \(B(x)\) 放到 \(A(x)\) 的虚部上,求出 \(A(x)^2\),然后把它的虚部 \(\times \tfrac{1}{2}\) 即为答案。

    证明:

    \[(a+bi)^2=(a^2-b^2)+(2abi) \]


标签:系数,多项式,FFT,初学,点值,quad,tfrac,傅里叶
From: https://www.cnblogs.com/ereoth/p/17899847.html

相关文章

  • Python 初学之华为OD机试题:求最大数字
    题目描述给定一个由纯数字组成以宇符串表示的数值,现要求字符串中的每个数字最多只能出现2次,超过的需要进行删除;删除某个重复的数字后,其它数字相对位置保持不变。如"34533”,数字3重复超过2次,需要册除其中一个3,删除第一个3后获得最大数值"4533"。请返回经过删除操作后的最大的数值......
  • 傅里叶级数@正弦级数和余弦级数@奇偶延拓和周期延拓
    文章目录abstract正弦级数和余弦级数周期延拓奇偶延拓对延拓函数做区间限制小结偶延拓方法奇延拓方法例abstract傅里叶级数@正弦级数和余弦级数@奇偶延拓和周期延拓正弦级数和余弦级数奇函数的傅里叶级数是只含有正弦项的正弦级数偶函数的傅里叶级数是只含有余弦项的余弦级数准确......
  • 傅里叶级数公式及其收敛问题
    文章目录abstract傅里叶级数公式及其收敛问题介绍周期为的情形下,函数的傅里叶级数公式至于一般周期,可转化为周期进行讨论,并得出相应公式(另见它文)函数展开成傅里叶系数设是周期为的周期函数,且能展开为三角级数式(6),即=这就产生了一个重要问题,如何计算式(6)中的系数,或说确......
  • 初学指针,刷题(hznu【C系列5.6】指针专题之翻译)
    题目如下Description (本人学艺不精,写了很久才写出了一个臃肿的代码,malloc也不咋会用,只能向ai请教了T_T)Alex在朋友们都去生猴子了的日子里,日复一日、年复一年地敲代码,终于,在经年累月的摧残下,她的手指变得不那么利索了,比如“how are you”她会哆嗦着打成“hhoow areee youu......
  • 《初学C语言第19天》
    //////——————————————-作业题//////写一个二分查找函数//////功能:在一个升序数组中查找指定的数值,找到了就返回下标,找不到就返回-1.//////arr是查找的数组//////left数组的左下标//////right数组的右下标//////key要查找的数字//#include<stdio.h>//......
  • 《初学C语言第18天——扫雷游戏特别篇》
    //(game.h.cpp)#define_CRT_SECURE_NO_WARNINGS1#defineROW9#defineCOL9#defineROWSROW+2#defineCOLSCOL+2#defineLEI10//雷的个数10#include<stdio.h>#include<stdlib.h>#include<time.h>//函数声明voidInitBoard(charboard[ROWS][COLS],......
  • m基于FPGA的OFDM系统verilog实现,包括IFFT,FFT,成型滤波以及加CP去CP,包含testbench
    1.算法仿真效果vivado2019.2仿真结果如下:CP加入,删除效果:系统RTL结构图:2.算法涉及理论知识概要正交频分复用(OrthogonalFrequencyDivisionMultiplexing,OFDM)是一种高效的无线通信技术,已经被广泛应用于无线通信领域。OFDM技术的主要优势在于其可以有效地抵抗多径效应和频率......
  • m基于FPGA的OFDM系统verilog实现,包括IFFT,FFT,成型滤波以及加CP去CP,包含testbench
    1.算法仿真效果vivado2019.2仿真结果如下:   CP加入,删除效果:   系统RTL结构图:   2.算法涉及理论知识概要          正交频分复用(OrthogonalFrequencyDivisionMultiplexing,OFDM)是一种高效的无线通信技术,已经被广泛应用于无线通信领域。OFDM......
  • 《初学C语言第17天》
    ////浮点数在内存中的存储//常见的浮点数://3.14159//1E10=1.0*10^10//浮点数家族包括:float、double、longdouble类型。//浮点数表示的范围:float.h中定义//浮点数存储的例子//#include<stdio.h>//intmain()//{// intn=9;// float*pFloat=(float*)&n;// printf......
  • 生成函数初学
    生成函数初学定义生成函数:指无穷级数与函数的对应,其中无穷级数表示一个无限的数列的和。我们定义一个生成函数\(f(x)\)是收敛的,当且仅当\(f(x)\)随着\(x\)的定向变化趋向于一个确定的极限值。如令\(f(x)=\dfrac{1}{x}\),当\(x\rightarrow\infty\)时,\(f(x)=\dfrac{1}{x......