让我给你讲清楚 快速傅里叶变换(FFT)(一): 数学原理详解 大家好啊, 今天我们来学习一个非常伟大和美丽的算法. 快速傅里叶变换. 0.为什么要用快速傅里叶变换 想象一个需求, 你需要对两个多项式, 或者一个超大的整数进行乘法运算. 最自然的, 肯定是直接将多项式或者整数的每一位和另一个多项式或整数的每一位相乘. 这种方法叫朴素乘法, 不难看出, 朴素乘法的复杂度是
当两个多项式或整数的长度为
的时候, 这个算法要进行
次乘法运算, 效率实在是太低了. 有没有什么方法可以减少运算量呢?
实在是太大了, 如果能优化到
就好了. 这就是我们今天要讲的快速傅里叶变换, Fast Fourier Transform. 1.多项式的系数表示法 我们知道, 对任意的多项式, 都可以表示为
这个方法也可以表示任意进制的整数, 例如, 就有
为了方便讲解, 我们之后仅提及多项式, 因为对于大整数的处理和多项式完全一样 对于多项式
, 我们又有向量表示法, 即:
如果省略
, 我们就只需要用向量
表示多项式
, 这就是多项式的系数表示法. 2.多项式的点值表示法 实际上, 多项式还可以用点值表示, 对于任意的多项式
, 如果带入
个不同的点, 必定得到
个值, 即带入
就能得到
现在, 我们来讨论一个问题, 能否在仅知道
向量的情况下, 确定多项式
, 换言之, 能否通过多项式的在各个点的值, 来确定多项式. 这个是可以的, 但是为什么? 如果我们写出
的矩阵方程形式, 就有,
所以有,
很明显, 这个矩阵的行列式是个范德蒙行列式(的转置), 而范德蒙行列式一定可逆, 所以这个矩阵方程只有唯一解, 所以
个不同的点所确定的
个值必定能唯一确定多项式
3.多项式乘积的点值表示. 假设现在有一个
和一个多项式
, 其对应点值向量
,
, 那么假设
, 就有
的点值表示
表示向量的按素相乘, 值写回原位置. 即
因此, 从
的点值表示到
的点值表示仅需要
次乘法, 因此复杂度是
我们好像看到一点希望了, 我们现在来捋一下思路如果我们能将两个多项式的系数表示转为其各自点值表示再将这两个多项式的对应点值相乘再将相乘后的点值表示转回系数表示我们就得到了两个多项式相乘的结果, 并且是系数表示的 不错不错, 思路就是这样, 但是有几个问题怎么将系数表示转换为点值表示怎么将点值表示转回系数表示 我们下面就来研究这两个问题 接下来, 也是这个算法最美妙的部分. 4.系数表示转点值表示 很自然的, 我们想到可以带入自然数列
到
和
, 这样就得到了
和
的点值表示. 但是有个问题, 这个算法对于一个多项式, 一共要做
次加法, 还要做至少
次乘法, 因此这个算法的时间复杂度还是
我们试着优化一下. 我们注意到, 一个多项式一定会有奇数次项, 例如
, 和偶数次项, 例如
. 而对于奇数次项来说, 一定有
而对于偶数次项来说, 一定有
那么对于只有奇数项或者只有偶数项的多项式来说, 我们只需要求出
这
个点的值, 我们就能按照函数的奇偶性求出
, 这样一来, 我们只需要求
个点的值, 就能确定
个点的值. 但是具体要怎么做呢? 现在, 我们再将
阶多项式(意思是
的最高次是
), 扩增到
阶.
, 原来不存在的要补成
例如
现在我们将
分成奇数次项和偶数次项. 即:
而对于任意的
来说, 一旦我们知道了
, 我们就能在
的时间内知道
, 同样, 我们也能在
的时间里知道
之后, 我们计算
只需要
的时间 因此, 我们能在
的时间里面知道
, 而这时候
所以一旦我们求出了
和
, 我们就求出了
和
. 而求
和
都是求
需要花费的时间的一半, 这样一来, 我们花费的时间和求
相同, 但是同时我们又能求出
, 相当于花了原来一半的时间就能求出
如果我们将这个过程递归下去, 假设原来需要花
的时间求解
, 现在最终只需要花
的时间. 是的, 这时候, 我们又可以将
视作一个新的多项式函数, 则有
同样对于
, 有
如果这个过程能够正常递归下去, 我们就能将原来需要花
的时间求解
, 优化到最终只需要花
的时间. 但是这里有点问题 第一次递归的时候, 我们需要求出的是
这要求
是正负配对的. 这个容易做到. 但是第二次递归, 我们需要求出的是
和
这要求由
平方之后的数也要是正负配对的, 这个就有点难做到了 更一般的, 如果我们要递归到最后一层, 那么就要求
都是正负配对的. 这个问题要怎么解决? 如果解决不了, 我们的递归就进行不下去. 5.复数的引入 不难发现, 为了解决以上的问题, 我们必须要引入复数. 但是这个
要怎么设计才能让其每次平方都能达到正负配对的结果? 注意到有欧拉公式, 世界上最漂亮的公式
所以有
所以有
所以, 我们注意到对任意的
, 如果选取
那么对这些数平方之后还是能达到正负配对的效果, 为什么? 我们现在只看
, 如果选取
对于任意的
, 都有
, 这个在前面已经证明. 而他们平方之后, 不过是由
变成了
, 不会影响正负配对的特性. 所以, 如果我们设
, 那么就有
所以, 我们要求的点值向量, 就变成了求
, 而求这个向量的方法, 就是之前提到的分治法. 即
不过这个
具体要怎么在计算机中表示呢? 实际上, 根据欧拉公式
, 我们就有
这就可以用C/C++中中定义的或者 表示了. 6.点值表示转回系数表示 虽然上面讲的分治法一般用递归写比较方便, 但是在实际工程中, 我们一般不用递归的方法. 不过我们现在假设我们已经求出了.
和
那么我们就得到了
的点值向量
. 不过这种点值向量不是人眼能够看的, 我们需要将其转回系数向量. 也就是研究多项式点值表示转回系数表示. 同样, 我们写出
的点值向量的矩阵方程形式.
其中,
因此
那么这个
等于什么? 我们令其为
矩阵, 则有
, 而对于任意的
有,
, 对于任意的
,
而
, 这时候我们发现, 如果取
, 那么就有
而同时, 对于任意
, 都有
又因为
次方和和
次方差公式
对任意
(本文仅讨论
的情况), 都有
, 所以
所以
所刻画的矩阵是矩阵方程
的一个解, 而又因为对于可逆矩阵来说, 该矩阵方程仅有一个解 所以
所刻画的矩阵是矩阵
的逆矩阵. 而这个逆矩阵到底长什么样呢? 注意到
是
的共轭复数. 所以这个逆矩阵就是
也就是说,
, 那么
就这么简单 所以, 我们在将点值表示转回系数表示只需要将
改为
之后, 再将得到的结果除以
就是最终的结果了. 至此, 我们就求出了
的结果. 以上就是快速傅里叶变换, Fast Fourier Transform的全过程. 这个算法的时间复杂度是
, 在长度为一百万的时候, 所需时间只相当于朴素乘法的五万分之一. 本文只是对快速傅里叶变换的数学原理的详细解释, 下篇文章我们讲一讲具体怎么用代码, C语言, 实现快速傅里叶. 不过注意我只讲迭代版本, 也就是蝶变版本的, 递归版本的不是特别实用而且速度较慢. 下下篇文章讲什么呢? 当然是讲快速傅里叶变换的并行实现啊. (也许吧, 可能鸽了) 第二篇文章:Pandora Eartha:让我给你讲清楚 快速傅里叶变换(FFT)(二): C语言实现迭代版本(蝶变操作)+超大整数乘法 第三篇文章估计得等等了. 文章封面(AI生成): 絵画のような蛍ちゃん(原神) 原图太大了,
分辨率的, 知乎不让上传.
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/52629.html