快速傅里叶变换 FFT 算法 | 分治策略、蝶形运算与旋转因子

注:本文为 “快速傅里叶变换 FFT 算法 ” 相关合辑。
图片清晰度受引文原图所限。
略作重排,未整理去重。
如有内容异常,请看原文。


彻底搞懂快速傅里叶变换 FFT 思想——分而治之

牙非涯 发布于 2022-02-27 22:44

通过离散傅里叶变换与窗函数,完成了对实际信号的傅里叶变换运算。即便处理时长较短的信号,该运算的计算复杂度仍较高。采用分而治之策略对问题进行分解,可显著降低计算开销。

分而治之是快速傅里叶变换(FFT)的构成基础。FFT 算法首次发表于 1965 年题为 An Algorithm for the Machine Calculation of Complex Fourier Series 的学术论文,由 IBM 研究员 James Cooley 与普林斯顿大学教授 John Tukey 共同提出。

什么是分而治之

首先考察与傅里叶变换无关的基础问题:给定包含 16 个数值的序列,求解序列中的最大值。

img

常规求解方式为顺序遍历并逐次比较,以确定 16 个数值中的最大值。该方法的操作复杂度与序列长度及最大值位置相关,整体过程较为繁琐。

更为高效的思路是将原问题分解为规模逐步减小的子问题,直至子问题具有直接求解的简单形式,该思路即为分而治之。将包含 16 个数值的序列划分为 2 组,每组包含 8 个数值;前 8 个数值构成第一组,后 8 个数值构成第二组。进一步将序列分解为 8 组,每组包含 2 个数值。

img

对上述 8 组数值分别执行比较操作,保留每组中的较大值并以橙色标记,舍弃较小值。重复该过程直至仅剩余一个数值,该数值即为序列最大值。该过程为分治法求解最大值问题。
总比较次数为:
8 + 4 + 2 + 1 = 15 8 + 4 + 2 + 1 = 15 8+4+2+1=15
该比较次数显著少于顺序查找方式。

img

分而治之在 FFT 中的应用

将分治法的执行阶段应用于傅里叶变换,可归纳为以下三个步骤:

  • DIVIDE:将样本序列划分为长度为原长度一半的子序列,直至每个子序列仅包含一对样本
  • CONQUER:对每一对样本执行离散傅里叶变换(DFT)
  • COMBINE:利用子序列 DFT 结果进行组合,生成下一阶段的输入序列

重复执行 CONQUERCOMBINE 阶段,直至得到最终变换结果。

第一阶段:划分

DFT 无法直接采用数值比较类问题的划分方式。对于周期为 T T T 的余弦波与正弦波,在 DFT 计算中,相隔一个周期 T T T 的离散点对应的复指数取值相等,仅信号取值 x ( n ) x(n) x(n) 存在差异。因此仅需存储一个周期内的 cos ⁡ \cos cos 与 sin ⁡ \sin sin 取值。
离散傅里叶变换定义为:
X ( k ) = ∑ n = 0 N − 1 x ( n ) cos ⁡ ( 2 π k n N ) − i ∑ n = 0 N − 1 x ( n ) sin ⁡ ( 2 π k n N ) X(k) = \sum_{n=0}^{N-1} x(n)\cos\left(\frac{2\pi kn}{N}\right)- i\sum_{n=0}^{N-1} x(n)\sin\left(\frac{2\pi kn}{N}\right) X(k)=n=0∑N−1​x(n)cos(N2πkn​)−in=0∑N−1​x(n)sin(N2πkn​)

以周期为 2 π 2\pi 2π 的余弦波为例,时域中相隔 2 π 2\pi 2π(对应索引间隔为 8)的点取值相等。该性质为序列分组提供理论依据。

img

随着余弦波频率的提升,该周期性依然成立。考察索引为 0 与 8 的两个点(间隔为一个周期的点对)。

设原始离散信号的样本点数为 16,如图中绿线所示,蓝线为参考余弦波。傅里叶级数运算为信号取值与对应余弦波取值相乘后累加。

img
img

频率提升过程中,索引 0 处取值保持不变,索引 8 处取值在 1 与 -1 之间交替。频率增加 2 Hz 后取值回归初始值 1。
在该示例中,频率为 0 Hz、2 Hz、4 Hz、6 Hz、8 Hz 等条件下,由索引 0 与 8 构成的点对对应的 DFT 结果相等。即每隔 2 Hz,无需重复执行乘加运算,可直接复用前期计算结果。

对于索引 4 与 12 构成的点对,存在同类规律:其计算结果在 0 Hz、4 Hz、8 Hz 等频率处重复,即每隔 4 Hz 重复一次。
通过类推可得到其余点对的重复规律。对前期计算结果的重复利用,可减少运算次数,该机制构成了快速傅里叶变换高效性的来源。

img
img

如何找到这些分组

img

基于前述两条结论,点对之间的时间间隔对应一个信号周期。对于长度为 16 的信号序列,可确定点对为:0 与 8、1 与 9、2 与 10……

为便于后续组合计算,对点对执行排序,确定计算优先级:按点对取值重复出现的频率由高到低排序
例如,点对 0 与 8 在频率 0、2、4、6、8……处均出现相同取值,共重复 8 次。样本 0 与 8 的重复频率最高,样本 7 与 15 的重复频率最低。

至此,通过分治算法将整体计算分解为若干小规模子块。各子块的快速求解方式将在下一章内容中阐述:蝴蝶操作。


彻底搞懂快速傅里叶变换 FFT——蝴蝶操作

牙非涯 发布于 2022-02-27 22:50

在上一章内容中,阐述了分治法在傅里叶变换中的应用思路,以及将信号分解为仅包含一对样本的子序列的方法。对两个样本执行 DFT 具有直接求解的形式。为进一步降低计算量,引入蝴蝶图结构。该运算结构的几何形态与蝴蝶翅膀形态相似,故得名蝴蝶图。

img

划分阶段的样本对重组

在划分阶段完成后,长度为 16 的样本信号被分解为 8 个样本对,并按照特定规则完成排序,结果如下。

在这里插入图片描述

对第一个样本对 sample- 0 \text{sample-}0 sample-0 与 sample- 8 \text{sample-}8 sample-8 执行 DFT 运算。将该两个样本输入第一个蝶形运算结构。

img

蝴蝶操作的基本定义

蝴蝶操作属于联合计算结构,运算形式如图所示。输入值 x 0 x_0 x0​ 与 x 8 x_8 x8​ 被重复调用参与运算,其中下方支路乘以因子 − 1 -1 −1,得到两个输出结果,记为 a 0 a_0 a0​、 a 1 a_1 a1​。 x 0 x_0 x0​、 x 8 x_8 x8​ 分别为索引 0 与 8 对应的信号取值。

2 个样本 DFT 计算

在执行两个样本点的 DFT 之前,给出相关定义:周期信号 x ( n ) x(n) x(n) 可表示为若干正弦波的叠加,每一正弦波具有频率、幅度与相位三个属性。
当信号仅包含 2 个采样点时,其频域表示最多包含 2 个正弦分量,因此仅需考察 2 个频率分量。
为简化计算,设采样率 R R R 与样本个数 N N N 相等,即 N = 2  Hz/s N = 2\ \text{Hz/s} N=2 Hz/s。此时考察的两个频率为 0 Hz 与 1 Hz。

下面计算仅包含样本点 0 与 8 的离散傅里叶变换。
img

0 Hz 余弦分量:蓝线为频率 0 Hz 的余弦波,绿线为待分析信号。

R ( a 0 ) = ∑ n = 0 N − 1 x ( n ) × cos ⁡ ( 2 π k n N ) = x 0 × 1 + x 8 × 1 \begin{align*} \mathcal{R}(a_0) & = \sum_{n=0}^{N-1} x(n) \times \cos\left(2\pi k \frac{n}{N}\right) \\ & = x_0 \times 1 + x_8 \times 1 \end{align*} R(a0​)​=n=0∑N−1​x(n)×cos(2πkNn​)=x0​×1+x8​×1​

依据傅里叶变换公式,频率为 0 时的余弦分量结果为 x 0 + x 8 x_0 + x_8 x0​+x8​,即两点取值相乘后求和。同理可得 1 Hz 余弦分量结果为 x 0 − x 8 x_0 - x_8 x0​−x8​。

img

1 Hz 余弦分量:蓝线为频率 0 Hz 的余弦波,绿线为待分析信号。

R ( a 1 ) = x 0 × 1 + x 8 × − 1 \mathcal{R}(a_1) = x_0 \times 1 + x_8 \times -1 R(a1​)=x0​×1+x8​×−1

同理计算正弦分量,结果均为 0。该结果可直接由 DFT 公式推导得到。
回顾前述蝴蝶操作,可见两点 DFT 计算结果与蝴蝶操作输出完全一致。

img

蝴蝶操作的推广限制

由此可得到推论:在第一阶段中,可求解所有点对在 0 Hz 与 1 Hz 处的频率分量,即

img

实际运算过程并不满足该简单推论。考察索引 4 与 12 构成的点对,由 DFT 公式可知,其频率为 1 的分量结果为 0,与前述蝴蝶操作结果不一致。其中 a 2 = x 4 + x 12 a_2 = x_4 + x_{12} a2​=x4​+x12​,因此无法直接执行简单的重复运算。

img

1 Hz 余弦分量:蓝线为频率 0 Hz 的余弦波,绿线为待分析信号。

相位平移与旋转因子的引入

为解决该问题,可对信号执行相位平移,使索引 4 与 12 处取值为 1 或 -1。该操作仅改变原始信号的相位,且可通过蝴蝶操作实现简化计算。
相位平移对最终结果的影响,将通过旋转因子进行补偿,该内容将在下一章中详细阐述。

img

彻底搞懂快速傅里叶变换 FFT——旋转因子

牙非涯 发布于 2022-02-28 20:03

上一篇文章引入蝴蝶操作完成样本对的 DFT 计算,实现分而治之策略中简单子问题的求解,同时引入信号相位改变的问题。为保证整体计算结果不变,采用旋转因子对相位平移后的信号进行补偿,所得结果作为下一阶段计算的输入。

组合计算流程

在引入旋转因子之前,首先对下一阶段的组合计算进行说明。

在这里插入图片描述


16 个样本点的 FFT

依据分而治之思想,DIVIDE 与 CONQUER 阶段已完成,后续进入 COMBINE 阶段,即对样本对的计算结果进行组合,形成新的样本序列。
按照计算顺序,将 2 点样本对合并为 4 点样本序列。对于长度为 4 的离散信号,依据 DFT 原理,需要对 4 个频率分量进行求解。
前期已完成 0 Hz 与 1 Hz 分量的计算,组合阶段需要补充求解 2 Hz 与 3 Hz 分量。
由正余弦函数的周期性可知,频率间隔为 2 Hz 时对应余弦波取值相等,即 0 Hz 与 2 Hz 的计算结果一致,1 Hz 与 3 Hz 的计算结果一致。

对由点 0、8、4、12 构成的 4 点信号,求解频率为 0 时的 DFT 结果,可表示为 a 0 + a 2 a_0 + a_2 a0​+a2​。
由于 a 2 a_2 a2​ 对应的信号已发生相位平移,需要乘以旋转因子 W 4 0 W_4^0 W40​ 进行补偿,再进行求和得到 b 0 b_0 b0​,即为 4 点信号在频率 0 处的 DFT 结果。
同理可完成 b 1 b_1 b1​、 b 2 b_2 b2​、 b 3 b_3 b3​ 的求解。

img

旋转因子定义与性质

本章对旋转因子(亦称为相位因子)进行系统阐述。
旋转因子采用符号 W W W 表示,附带下标与上标:

  • 下标表示蝶形运算的点数,称为旋转因子的阶数
  • 上标表示旋转因子的索引

旋转因子为复数,在信号进入下一阶段蝶形运算之前施加,其作用为对相位平移后的信号进行补偿,保证整体 DFT 结果不变。

定义式如下:

img

在 4 点蝶形运算中,共需要 2 个旋转因子,仅第 3、第 4 个输入需要进行相位补偿,对应索引为 0 与 1。
旋转因子索引的取值范围为 0 至阶数的一半,该取值由初始样本对的计算顺序决定。

img

旋转因子与原始信号的关系

设原始信号为 x ( n ) x(n) x(n),分解形式可表示为:
x ( n ) = W ⋅ x ~ ( n ) x(n) = W\cdot \tilde{x}(n) x(n)=W⋅x~(n)
其中 x ~ ( n ) \tilde{x}(n) x~(n) 为经过相位平移后的信号,红圈标记对应蝴蝶操作的输出结果。

img

结果验证: b 0 b_0 b0​ 与 b 1 b_1 b1​ 计算

对组合结果进行验证,首先计算 4 点信号在频率 0 处的傅里叶级数。

img


4个点组合在频率为0的傅里叶级数

b 0 = x 0 + x 4 + x 8 + x 12 b_0 = x_0 + x_4 + x_8 + x_{12} b0​=x0​+x4​+x8​+x12​

继续计算频率 1 对应的输出 b 1 b_1 b1​。

在这里插入图片描述


b 1 = ( x 0 − x 8 ) + i ( x 4 − x 12 ) b_1 = (x_0 - x_8) + i(x_4 - x_{12}) b1​=(x0​−x8​)+i(x4​−x12​)

计算表明, b 0 b_0 b0​ 与 b 1 b_1 b1​ 的结果与蝶形运算输出一致。
第二个旋转因子的计算结果为 − i -i −i。
旋转因子取值为 1 时,对应原始信号未发生相位平移;取值为 − i -i −i 时,对应信号向右平移 π / 2 \pi/2 π/2。

W 4 1 = cos ⁡ ( 2 π × 1 4 ) − i ⋅ sin ⁡ ( 2 π × 1 4 ) = cos ⁡ ( π 2 ) − i ⋅ sin ⁡ ( π 2 ) = 0 − i \begin{align*} W^{1}_{4} & = \cos\left(2\pi \times \frac{1}{4}\right) - i \cdot \sin\left(2\pi \times \frac{1}{4}\right) \\ & = \cos\left(\frac{\pi}{2}\right) - i \cdot \sin\left(\frac{\pi}{2}\right) \\ & = 0 - i \end{align*} W41​​=cos(2π×41​)−i⋅sin(2π×41​)=cos(2π​)−i⋅sin(2π​)=0−i​

旋转因子的相位补偿机制

对旋转因子实现信号来回平移的机理进行说明。
原始信号 x ( n ) x(n) x(n) 经过相位平移得到 x ~ ( n ) \tilde{x}(n) x~(n)。

img

旋转因子取值为 1 时,信号不发生平移;取值为 − i -i −i 时,对应相位变化。
为适配蝴蝶操作,原始信号向左平移 4 个刻度,对应相位平移 π / 2 \pi/2 π/2;
完成初次蝴蝶运算后,乘以旋转因子 W W W,将信号向右平移 π / 2 \pi/2 π/2,实现相位补偿。

乘以 − i -i −i 与相位平移 π / 2 \pi/2 π/2 具有等效性,两种操作对信号产生的变换结果一致。

img

至此,蝴蝶操作与结果组合的基本流程已完成。将该结构扩展至完整信号并解释 FFT 最终输出,将在下一篇文章中给出。

img

彻底搞懂快速傅里叶变换 FFT——算法输出

牙非涯 发布于 2022-02-28 20:20

上一篇文章引入旋转因子,完成任意点对的蝶形运算,并实现 2 点样本到 4 点样本的组合。
在此基础上,可将 4 组 4 点蝶形组合为 2 组 8 点蝶形,再进一步组合为 1 组 16 点蝶形,得到最终输出。
FFT 算法的输出为对应 16 个不同频率的正弦波分量集合。
完整复现关键步骤的推导与计算,有助于理解算法机理。

img

4 点到 8 点的组合扩展

4 点蝶形运算包含 2 个旋转因子,8 点蝶形运算则包含 4 个旋转因子。
在 FFT 中,旋转因子的数量为对应蝶形点数的一半。

在 2 点蝶形阶段,样本 4 与 12 经过相位平移得到结果 a 2 a_2 a2​、 a 3 a_3 a3​;
在 4 点蝶形阶段,通过旋转因子补偿得到 b 2 b_2 b2​、 b 3 b_3 b3​;
该阶段前 4 个点 b 0 ∼ b 3 b_0 \sim b_3 b0​∼b3​ 位于原始位置,不再需要旋转因子。

img

样本点 2、10 与 6、14 对应的 2 点蝶形输出 a 4 a_4 a4​、 a 5 a_5 a5​、 a 6 a_6 a6​、 a 7 a_7 a7​,在 4 点蝶形输出后仍存在相位偏移。
因此在 8 点蝶形阶段,需要引入额外旋转因子完成补偿。

img

最终将 8 点序列组合为 16 点序列,完成全部 FFT 计算。

img

FFT 算法输出形式

对完整 FFT 计算流程进行总结,各阶段输出可归纳为:

  • a a a:2 点蝶形运算结果
  • b b b:4 点蝶形运算结果
  • c c c:8 点蝶形运算结果
  • d d d:16 点蝶形运算结果,即 FFT 最终输出

FFT 输出为一组复数序列:

img

在 16 点信号示例中,共对 16 个频率分量进行求解,得到 16 组复数。
由该复数序列可求解对应正弦波的频率、幅度与相位,进而生成频谱图与相位图。

FFT 输出的幅度与相位计算

设 x [ n ] x[n] x[n] 为长度为 N N N 的时域离散信号, n = 0 , 1 , … , N − 1 n = 0, 1, \ldots, N-1 n=0,1,…,N−1。其 N N N 点 FFT 变换定义为:

X [ k ] = ∑ n = 0 N − 1 x [ n ] ⋅ e − j 2 π N k n , k = 0 , 1 , … , N − 1 X[k] = \sum_{n=0}^{N-1} x[n] \cdot e^{-j\frac{2\pi}{N}kn}, \quad k = 0, 1, \ldots, N-1 X[k]=n=0∑N−1​x[n]⋅e−jN2π​kn,k=0,1,…,N−1

其中 X [ k ] X[k] X[k] 为第 k k k 个频点对应的复数值, R e { X [ k ] } \mathrm{Re}\{X[k]\} Re{X[k]} 和 I m { X [ k ] } \mathrm{Im}\{X[k]\} Im{X[k]} 分别表示其实部与虚部。幅度计算

各频点的幅度由复数模运算求得:

∣ X [ k ] ∣ = R e { X [ k ] } 2 + I m { X [ k ] } 2 |X[k]| = \sqrt{\mathrm{Re}\{X[k]\}^2 + \mathrm{Im}\{X[k]\}^2} ∣X[k]∣=Re{X[k]}2+Im{X[k]}2​相位计算

各频点的相位由复数辐角确定:

ϕ [ k ] = arctan ⁡ ( I m { X [ k ] } R e { X [ k ] } ) \phi[k] = \arctan\left(\frac{\mathrm{Im}\{X[k]\}}{\mathrm{Re}\{X[k]\}}\right) ϕ[k]=arctan(Re{X[k]}Im{X[k]}​)

实际计算中通常采用四象限反正切函数(如 atan2)以避免象限模糊问题。

真实信号的完整 FFT 流程

16 点信号在实际应用中不具备代表性,下面对更贴近实际的信号进行分析。

设一段时长为 10 秒的连续信号,对其进行离散化采样,样本点数 N = 1024 N = 1024 N=1024,采样率:
R = 1024 10  Hz R = \frac{1024}{10}\ \text{Hz} R=101024​ Hz

频率索引 k k k 的取值范围为 0 ∼ N − 1 0 \sim N-1 0∼N−1,对应可分析的频率范围为 0 ∼ R 0 \sim R 0∼R。
在 DFT 框架下,频率间隔为 R / N R/N R/N,该间隔为可实现的最小频率分辨率。

img


连续真实信号 x ( t ) x(t) x(t)

img


FFT 计算结果

对该 1024 点信号执行 FFT,得到复数形式的输出,经转换可得到幅度与相位信息,据此生成频谱与相位谱。

在这里插入图片描述

傅里叶变换可将复杂周期信号分解为正弦波分量,FFT 则为计算机实现高效傅里叶变换的算法框架。
蝴蝶操作的结构便于计算机执行重复、规整的运算。


快速傅里叶变换 (FFT) 算法——蝶形变换的原理与实现

0小龙虾0 原创于 2019-12-09 22:21:15 发布

为实现基于 FFT 的海面模拟,需首先完成 FFT 算法的理论推导与工程实现。本文系统阐述 FFT 算法的数学构成,重点解析蝶形变换的数学逻辑。

离散傅里叶变换 (DFT)

在学习 FFT 算法前,需先掌握离散傅里叶变换(DFT)的基本定义。傅里叶变换用于实现时域信号到频域信号的转换,计算机无法直接处理连续信号,因此离散傅里叶变换(DFT)被提出以适配数字计算场景。

标准 DFT 变换的数学表达式为:
X ( k ) = ∑ n = 0 N − 1 x ( n ) e − i 2 π k N n , k ∈ { 0 , 1 , … , N − 1 } X(k)=\sum_{n=0}^{N-1}x(n)e^{-i\frac{2\pi k}{N}n},\quad k\in \{0,1,\dots,N-1\} X(k)=n=0∑N−1​x(n)e−iN2πk​n,k∈{0,1,…,N−1}

为简化表达式,定义旋转因子:
W N k = e − i 2 π k N W_{N}^{k}=e^{-i\frac{2\pi k}{N}} WNk​=e−iN2πk​

旋转因子 W W W 的基本性质

性质 1:缩放性

W N k = W 2 N 2 k W_{N}^{k}=W_{2N}^{2k} WNk​=W2N2k​

证明过程
根据欧拉公式 e − i θ = cos ⁡ θ − i sin ⁡ θ e^{-i\theta} = \cos\theta - i\sin\theta e−iθ=cosθ−isinθ,将旋转因子展开:
W N k = e − i 2 π k N = cos ⁡ ( − 2 π k N ) + i sin ⁡ ( − 2 π k N ) = cos ⁡ ( − 2 π ( 2 k ) 2 N ) + i sin ⁡ ( − 2 π ( 2 k ) 2 N ) = W 2 N 2 k \begin{aligned} W_{N}^{k} &= e^{-i\frac{2\pi k}{N}} = \cos\left(-\frac{2\pi k}{N}\right)+i\sin\left(-\frac{2\pi k}{N}\right) \\ &= \cos\left(-\frac{2\pi(2k)}{2N}\right)+i\sin\left(-\frac{2\pi(2k)}{2N}\right) = W_{2N}^{2k} \end{aligned} WNk​​=e−iN2πk​=cos(−N2πk​)+isin(−N2πk​)=cos(−2N2π(2k)​)+isin(−2N2π(2k)​)=W2N2k​​

性质 2:对称性

W N k + N 2 = − W N k W_{N}^{k+\frac{N}{2}}=-W_{N}^{k} WNk+2N​​=−WNk​

性质 3:周期性

W N 0 = W N N W_{N}^{0}=W_{N}^{N} WN0​=WNN​

性质 2 与性质 3 的证明方法与性质 1 一致,均通过欧拉公式展开后进行代数变换即可验证。

快速傅里叶变换 (FFT) 的数学推导

将 DFT 变换结果 X ( k ) X(k) X(k) 按输入序列索引的奇偶性拆分。当 k ∈ { 0 , 1 , … , N 2 − 1 } k\in \{0,1,\dots,\frac{N}{2}-1\} k∈{0,1,…,2N​−1} 时,原式可改写为:
X ( k ) = ∑ n = 0 N − 1 x ( n ) e − i 2 π k N n X(k)=\sum_{n=0}^{N-1}x(n)e^{-i\frac{2\pi k}{N}n} X(k)=n=0∑N−1​x(n)e−iN2πk​n

按奇偶索引拆分求和项:
X ( k ) = ∑ n = 0 N 2 − 1 x ( 2 n ) e − i 2 π k N ( 2 n ) + ∑ n = 0 N 2 − 1 x ( 2 n + 1 ) e − i 2 π k N ( 2 n + 1 ) = ∑ n = 0 N 2 − 1 x ( 2 n ) e − i 2 π k N / 2 n + e − i 2 π k N ∑ n = 0 N 2 − 1 x ( 2 n + 1 ) e − i 2 π k N / 2 n \begin{aligned} X(k) &= \sum_{n=0}^{\frac{N}{2}-1}x(2n)e^{-i\frac{2\pi k}{N}(2n)} +\sum_{n=0}^{\frac{N}{2}-1}x(2n+1)e^{-i\frac{2\pi k}{N}(2n+1)} \\ &= \sum_{n=0}^{\frac{N}{2}-1}x(2n)e^{-i\frac{2\pi k}{N/2}n} +e^{-i\frac{2\pi k}{N}}\sum_{n=0}^{\frac{N}{2}-1}x(2n+1)e^{-i\frac{2\pi k}{N/2}n} \end{aligned} X(k)​=n=0∑2N​−1​x(2n)e−iN2πk​(2n)+n=0∑2N​−1​x(2n+1)e−iN2πk​(2n+1)=n=0∑2N​−1​x(2n)e−iN/22πk​n+e−iN2πk​n=0∑2N​−1​x(2n+1)e−iN/22πk​n​

由于 e − i 2 π N e^{-i\frac{2\pi}{N}} e−iN2π​ 为与 n n n 无关的常数,可将 X ( k ) X(k) X(k) 表示为旋转因子的函数形式:
X ( e − i 2 π k N ) = ∑ n = 0 N − 1 x ( n ) e − i 2 π k N n X\left(e^{-i\frac{2\pi k}{N}}\right)=\sum_{n=0}^{N-1}x(n)e^{-i\frac{2\pi k}{N}n} X(e−iN2πk​)=n=0∑N−1​x(n)e−iN2πk​n

代入旋转因子定义 W N k = e − i 2 π k N W_N^k = e^{-i\frac{2\pi k}{N}} WNk​=e−iN2πk​,可得:
X ( W N k ) = ∑ n = 0 N − 1 x ( n ) ( W N k ) n = ∑ n = 0 N 2 − 1 x ( 2 n ) ( W N 2 k ) n + W N k ∑ n = 0 N 2 − 1 x ( 2 n + 1 ) ( W N 2 k ) n , k ∈ { 0 , 1 , … , N 2 − 1 } \begin{aligned} X(W_{N}^{k}) &= \sum_{n=0}^{N-1}x(n)\left(W_{N}^{k}\right)^{n} \\ &= \sum_{n=0}^{\frac{N}{2}-1}x(2n)\left(W_{\frac{N}{2}}^{k}\right)^{n} +W_{N}^{k}\sum_{n=0}^{\frac{N}{2}-1}x(2n+1)\left(W_{\frac{N}{2}}^{k}\right)^{n}, \quad k\in \{0,1,\dots,\tfrac{N}{2}-1\} \end{aligned} X(WNk​)​=n=0∑N−1​x(n)(WNk​)n=n=0∑2N​−1​x(2n)(W2N​k​)n+WNk​n=0∑2N​−1​x(2n+1)(W2N​k​)n,k∈{0,1,…,2N​−1}​

定义两个子序列的 DFT 结果:
F ( W N 2 k ) = ∑ n = 0 N 2 − 1 x ( 2 n ) ( W N 2 k ) n G ( W N 2 k ) = ∑ n = 0 N 2 − 1 x ( 2 n + 1 ) ( W N 2 k ) n \begin{aligned} F\left(W_{\frac{N}{2}}^{k}\right) &= \sum_{n=0}^{\frac{N}{2}-1}x(2n)\left(W_{\frac{N}{2}}^{k}\right)^{n} \\ G\left(W_{\frac{N}{2}}^{k}\right) &= \sum_{n=0}^{\frac{N}{2}-1}x(2n+1)\left(W_{\frac{N}{2}}^{k}\right)^{n} \end{aligned} F(W2N​k​)G(W2N​k​)​=n=0∑2N​−1​x(2n)(W2N​k​)n=n=0∑2N​−1​x(2n+1)(W2N​k​)n​

则当 k ∈ { 0 , 1 , … , N 2 − 1 } k\in \{0,1,\dots,\frac{N}{2}-1\} k∈{0,1,…,2N​−1} 时, X ( W N k ) X(W_N^k) X(WNk​) 可表示为:
X ( W N k ) = F ( W N 2 k ) + W N k G ( W N 2 k ) X(W_{N}^{k})=F\left(W_{\frac{N}{2}}^{k}\right)+W_{N}^{k}\,G\left(W_{\frac{N}{2}}^{k}\right) X(WNk​)=F(W2N​k​)+WNk​G(W2N​k​)

接下来推导 k + N 2 k+\frac{N}{2} k+2N​ 处的结果 X ( W N k + N 2 ) X(W_N^{k+\frac{N}{2}}) X(WNk+2N​​),其中 k ∈ { 0 , 1 , … , N 2 − 1 } k\in \{0,1,\dots,\frac{N}{2}-1\} k∈{0,1,…,2N​−1}:
X ( W N k + N 2 ) = F ( W N 2 k + N 2 ) + W N k + N 2 G ( W N 2 k + N 2 ) = F ( W N 2 k + N ) + W N k + N 2 G ( W N 2 k + N ) = F ( W N 2 k W N N ) − W N k G ( W N 2 k W N N ) = F ( W N 2 k ) − W N k G ( W N 2 k ) \begin{aligned} X\left(W_{N}^{k+\frac{N}{2}}\right) &= F\left(W_{\frac{N}{2}}^{k+\frac{N}{2}}\right) +W_{N}^{k+\frac{N}{2}}\,G\left(W_{\frac{N}{2}}^{k+\frac{N}{2}}\right) \\ &= F\left(W_{N}^{2k+N}\right) +W_{N}^{k+\frac{N}{2}}\,G\left(W_{N}^{2k+N}\right) \\ &= F\left(W_{N}^{2k}W_{N}^{N}\right) -W_{N}^{k}\,G\left(W_{N}^{2k}W_{N}^{N}\right) \\ &= F\left(W_{\frac{N}{2}}^{k}\right) -W_{N}^{k}\,G\left(W_{\frac{N}{2}}^{k}\right) \end{aligned} X(WNk+2N​​)​=F(W2N​k+2N​​)+WNk+2N​​G(W2N​k+2N​​)=F(WN2k+N​)+WNk+2N​​G(WN2k+N​)=F(WN2k​WNN​)−WNk​G(WN2k​WNN​)=F(W2N​k​)−WNk​G(W2N​k​)​

综上,得到蝶形运算关系式:
{ X ( W N k ) = F ( W N 2 k ) + W N k G ( W N 2 k ) X ( W N k + N 2 ) = F ( W N 2 k ) − W N k G ( W N 2 k ) \left\{ \begin{aligned} X(W_{N}^{k}) &= F\left(W_{\frac{N}{2}}^{k}\right) + W_{N}^{k}G\left(W_{\frac{N}{2}}^{k}\right) \\ X\left(W_{N}^{k+\frac{N}{2}}\right) &= F\left(W_{\frac{N}{2}}^{k}\right) - W_{N}^{k}G\left(W_{\frac{N}{2}}^{k}\right) \end{aligned} \right. ⎩⎨⎧​X(WNk​)X(WNk+2N​​)​=F(W2N​k​)+WNk​G(W2N​k​)=F(W2N​k​)−WNk​G(W2N​k​)​

该组公式表明, N N N 点 DFT 结果的前半部分与后半部分可由其奇偶子序列的 N / 2 N/2 N/2 点 DFT 结果通过线性组合得到。

4 点 FFT 蝶形变换实例验证

令 N = 4 N=4 N=4,以 k = 0 k=0 k=0 为例展开计算,直观验证蝶形变换的计算逻辑。

首先计算 X ( W 4 0 ) X(W_4^0) X(W40​):
X ( W 4 0 ) = F ( W 2 0 ) + W 4 0 G ( W 2 0 ) = ∑ n = 0 1 x ( 2 n ) ( W 2 0 ) n + W 4 0 ∑ n = 0 1 x ( 2 n + 1 ) ( W 2 0 ) n \begin{aligned} X(W_{4}^{0}) &= F(W_{2}^{0})+W_{4}^{0}\,G(W_{2}^{0}) \\ &= \sum_{n=0}^{1}x(2n)\left(W_{2}^{0}\right)^{n} +W_{4}^{0}\sum_{n=0}^{1}x(2n+1)\left(W_{2}^{0}\right)^{n} \end{aligned} X(W40​)​=F(W20​)+W40​G(W20​)=n=0∑1​x(2n)(W20​)n+W40​n=0∑1​x(2n+1)(W20​)n​

其中子序列 DFT 结果 F ( W 2 0 ) F(W_2^0) F(W20​) 与 G ( W 2 0 ) G(W_2^0) G(W20​) 进一步递归拆分:
F ( W 2 0 ) = F f ( W 1 0 ) + W 2 0 G f ( W 1 0 ) = ∑ n = 0 0 x ( 4 n ) ( W 1 0 ) n + W 2 0 ∑ n = 0 0 x ( 4 n + 2 ) ( W 1 0 ) n = x ( 0 ) + x ( 2 ) W 2 0 \begin{aligned} F(W_{2}^{0}) &= F_{f}(W_{1}^{0})+W_{2}^{0}\,G_{f}(W_{1}^{0}) \\ &= \sum_{n=0}^{0}x(4n)\left(W_{1}^{0}\right)^{n} +W_{2}^{0}\sum_{n=0}^{0}x(4n+2)\left(W_{1}^{0}\right)^{n} \\ &= x(0)+x(2)\,W_{2}^{0} \end{aligned} F(W20​)​=Ff​(W10​)+W20​Gf​(W10​)=n=0∑0​x(4n)(W10​)n+W20​n=0∑0​x(4n+2)(W10​)n=x(0)+x(2)W20​​

G ( W 2 0 ) = F g ( W 1 0 ) + W 2 0 G g ( W 1 0 ) = ∑ n = 0 0 x ( 4 n + 1 ) ( W 1 0 ) n + W 2 0 ∑ n = 0 0 x ( 4 n + 3 ) ( W 1 0 ) n = x ( 1 ) + x ( 3 ) W 2 0 \begin{aligned} G(W_{2}^{0}) &= F_{g}(W_{1}^{0})+W_{2}^{0}\,G_{g}(W_{1}^{0}) \\ &= \sum_{n=0}^{0}x(4n+1)\left(W_{1}^{0}\right)^{n} +W_{2}^{0}\sum_{n=0}^{0}x(4n+3)\left(W_{1}^{0}\right)^{n} \\ &= x(1)+x(3)\,W_{2}^{0} \end{aligned} G(W20​)​=Fg​(W10​)+W20​Gg​(W10​)=n=0∑0​x(4n+1)(W10​)n+W20​n=0∑0​x(4n+3)(W10​)n=x(1)+x(3)W20​​

注: F f , G f F_f,\,G_f Ff​,Gf​ 为 F F F 对应的递归子序列 DFT 结果; F g , G g F_g,\,G_g Fg​,Gg​ 为 G G G 对应的递归子序列 DFT 结果。

因此 X ( W 4 0 ) X(W_4^0) X(W40​) 可写为:
X ( W 4 0 ) = x ( 0 ) + x ( 2 ) W 2 0 + W 4 0 ( x ( 1 ) + x ( 3 ) W 2 0 ) X(W_{4}^{0})=x(0)+x(2)\,W_{2}^{0}+W_{4}^{0}\left(x(1)+x(3)\,W_{2}^{0}\right) X(W40​)=x(0)+x(2)W20​+W40​(x(1)+x(3)W20​)

4 点 FFT 的蝶形变换结构如下图所示:

img

上述计算过程的分步图解如下(其中 X [ i ] = X ( W 4 i ) X[i] = X(W_4^i) X[i]=X(W4i​)):

img

子序列递归计算的图解:

img

完整的 4 点 FFT 蝶形变换图解:

img

通过蝶形变换,FFT 算法将 DFT 的计算复杂度从 O ( N 2 ) O(N^2) O(N2) 降低至 O ( N log ⁡ 2 N ) O(N\log_{2}N) O(Nlog2​N),提升了计算效率。

位逆序(bitreverse)算法

FFT 算法可通过非递归方式实现,其前提是对输入序列进行位逆序重排。以 4 点 FFT 为例,最终参与计算的输入序列为 x [ 0 ] , x [ 2 ] , x [ 1 ] , x [ 3 ] x[0],\,x[2],\,x[1],\,x[3] x[0],x[2],x[1],x[3];8 点 FFT 的输入序列位置变化过程为:
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 → 0 , 2 , 4 , 6 , 1 , 3 , 5 , 7 → 0 , 4 , 2 , 6 , 1 , 5 , 3 , 7 0,1,2,3,4,5,6,7 \to 0,2,4,6,1,3,5,7 \to 0,4,2,6,1,5,3,7 0,1,2,3,4,5,6,7→0,2,4,6,1,3,5,7→0,4,2,6,1,5,3,7

位逆序算法的规则为:对于 N N N 点 FFT,将输入索引 i i i 转换为 log ⁡ 2 N \log_2N log2​N 位二进制数,对二进制位进行逆序操作后再转换为十进制数,该数值即为输入序列 x [ i ] x[i] x[i] 应处的目标位置。

示例:在 8 点 FFT 中, x ( 4 ) x(4) x(4) 的索引 4 4 4 转换为 3 位二进制数为 100 100 100,逆序后为 001 001 001,对应十进制数 1 1 1,因此 x ( 4 ) x(4) x(4) 应放置在第 1 号位(索引从 0 开始)。

非递归 FFT 算法的工程实现

基于位逆序算法与蝶形变换,可编写迭代形式的 FFT 实现代码:

// 复数类型定义(可替换为 C++ 标准库的 complex<double>)using cp = complex<double>;int n;// FFT 的长度,需为 2 的整数次幂// FFT 迭代实现// 参数说明:a 为输入输出的复数数组,omg 为预计算的旋转因子数组voidfft(cp *a, cp *omg){int lim =0;while((1<< lim)< n) lim++;// 计算 log2(n),即二进制位数// 步骤 1:输入序列的位逆序重排for(int i =0; i < n; i++){int t =0;for(int j =0; j < lim; j++){// 逐位提取 i 的二进制值,并映射到逆序位置if((i >> j)&1) t |=(1<<(lim - j -1));}if(i < t)swap(a[i], a[t]);// 避免重复交换}// 步骤 2:逐层执行蝶形变换for(int l =2; l <= n; l *=2){// l 为当前蝶形单元的长度int m = l /2;// 蝶形单元的半长for(cp *p = a; p != a + n; p += l){// 遍历所有蝶形单元for(int i =0; i < m; i++){// 执行单个蝶形单元内的计算// 蝶形变换关系式 cp t = omg[n / l * i]* p[i + m]; p[i + m]= p[i]- t; p[i]+= t;}}}}

代码执行逻辑图解

  1. 第一层循环(蝶形单元长度 l l l 遍历)的分块计算逻辑:
img
  1. 第二层循环(蝶形单元遍历)的分块计算逻辑:
img
  1. 蝶形变换的计算逻辑:
img

迭代过程中,每一级的变换结果均可由当前级的计算结果自洽推导得出。完成上述实现后,即可将该 FFT 算法应用于海面模拟等工程场景。

总结

  1. FFT 算法通过拆分 DFT 为奇偶子序列的子问题,结合旋转因子的周期性、对称性与缩放性,建立蝶形运算关系式,将计算复杂度从 O ( N 2 ) O(N^2) O(N2) 降至 O ( N log ⁡ 2 N ) O(N\log_2N) O(Nlog2​N)。
  2. 非递归 FFT 实现包含两个步骤:通过位逆序算法重排输入序列,按蝶形单元长度逐层执行蝶形变换。
  3. 蝶形运算关系式描述了 N N N 点 DFT 结果与 N / 2 N/2 N/2 点子序列 DFT 结果之间的线性组合关系,这一结构对应蝶形变换的物理含义。

FFT 原理——详细推导理解 FFT 变换

ZhangP.H 原创于 2020-05-14 20:48:05 发布

概要

FFT(Fast Fourier Transform,快速傅里叶变换)是离散傅里叶变换(DFT)的工程化实现方式。直接求解 DFT 的计算复杂度较高,FFT 方法利用 DFT 求解过程中旋转因子的固有性质,并引入分治算法的设计思想,显著简化了计算流程,该方法被广泛应用于频谱分析的工程实践中,如 MATLAB、C、C++、CUDA 等编程语言或框架的底层实现逻辑中。

一、DFT 简介

频谱分析是信号处理领域的重要组成部分,从傅里叶变换(FT)、拉普拉斯变换(LT)、离散时间傅里叶变换(DTFT)、Z 变换(ZT),到本文讨论的离散傅里叶变换(DFT),各类变换具有不同的适用场景与数学特征(其相互联系与区别可参考作者其他研究成果)。

相较于其他变换形式,DFT 得以广泛应用的原因在于其输入的时域信号为离散形式,输出的频域结果同样为离散形式。这一特性为基于计算机的频谱计算、存储与分析提供了便利,符合数字信号处理的发展趋势。

DFT 变换的数学表达式为:
X [ k ] = ∑ n = 0 N − 1 x [ n ] e − j k 2 π K n ,   k = 0 , 1 , 2 , . . . , K − 1 X\left[ k \right]=\sum\limits_{n=0}^{N-1}{x\left[ n \right]{{e}^{-jk\frac{2\pi }{K}n}},\ k=0,1,2,...,K-1} X[k]=n=0∑N−1​x[n]e−jkK2π​n, k=0,1,2,...,K−1

与传统教材表述不同的是,此处 k k k 的取值范围不再与输入信号索引 n n n 的长度 0 ∼ N − 1 0 \sim N-1 0∼N−1 保持一致,而是可独立设定。这一设定旨在强调 k k k 的本质作用是对以 2 π 2\pi 2π 为周期的连续频谱进行离散化处理(DFT 是对 DTFT 连续频域结果进行离散化采样后的产物),即完成频谱的离散采样操作。

在这里插入图片描述

为便于分析,在 FFT 的计算过程中,通常选取 k = 0 ∼ N − 1 k = 0 \sim N-1 k=0∼N−1 的取值策略,此时 DFT 变换公式可表示为:
X [ k ] = ∑ n = 0 N − 1 x [ n ] e − j k 2 π N n ,   k = 0 , 1 , 2 , . . . , N − 1 X\left[ k \right]=\sum\limits_{n=0}^{N-1}{x\left[ n \right]{{e}^{-jk\frac{2\pi }{N}n}},\ k=0,1,2,...,N-1} X[k]=n=0∑N−1​x[n]e−jkN2π​n, k=0,1,2,...,N−1

上述公式可直接求解,但计算量较大,需执行 N 2 N^2 N2 次复数乘法运算与 N ( N − 1 ) N(N-1) N(N−1) 次复数加法运算。为简化表达式,引入旋转因子 W N k n = e − j k 2 π N n W_N^{kn} = e^{-jk\frac{2\pi}{N}n} WNkn​=e−jkN2π​n,则 DFT 公式可改写为:
X [ k ] = ∑ n = 0 N − 1 x [ n ] e − j k 2 π N n = ∑ n = 0 N − 1 x [ n ] W N k n X\left[ k \right]=\sum\limits_{n=0}^{N-1}{x\left[ n \right]{{e}^{-jk\frac{2\pi }{N}n}}=\sum\limits_{n=0}^{N-1}{x\left[ n \right]W_{N}^{kn}}} X[k]=n=0∑N−1​x[n]e−jkN2π​n=n=0∑N−1​x[n]WNkn​

其中,旋转因子的完整定义为: W N k n = e − j k 2 π N n W_{N}^{kn} = {{e}^{-jk\frac{2\pi }{N}n}} WNkn​=e−jkN2π​n, W = e − j 2 π N W = {{e}^{-j\frac{2\pi }{N}}} W=e−jN2π​。FFT 算法对 DFT 计算过程的简化,正是依托旋转因子 W W W 的若干基本性质实现的。

二、旋转因子 W W W 的性质

旋转因子具有以下数学性质,这些性质是简化 DFT 计算的关键:

  1. 周期性: W N a + N = W N a W_{N}^{a+N} = W_{N}^{a} WNa+N​=WNa​
  2. 对称性: W N a + N / 2 = − W N a W_{N}^{a+N/2} = -W_{N}^{a} WNa+N/2​=−WNa​
  3. 缩放性: W N 2 = W N / 2 1 W_{N}^{2} = W_{N/2}^{1} WN2​=WN/21​

上述性质可通过旋转因子的定义式直接展开推导,本质为基本的代数变换操作。这些性质表明,计算过程中存在大量重复的数值结果,无需重复计算,由此可有效降低 DFT 的计算复杂度。

三、FFT 蝶形计算推导

FFT 的计算流程融合了分治算法的设计思想,并结合旋转因子 W W W 的性质实现计算简化,具体推导过程如下:

步骤 1:输入信号的奇偶分解

将输入时域信号 x [ n ] ,   n = 0 , 1 , . . . , N − 1 x[n],\ n=0,1,...,N-1 x[n], n=0,1,...,N−1 按索引的奇偶性拆分为两个子序列:
f e v e n [ n ] = x [ 2 n ] f o d d [ n ] = x [ 2 n + 1 ] f_{even}\left[ n \right] = x\left[ 2n \right]\\f_{odd}\left[ n \right] = x\left[ 2n+1 \right] feven​[n]=x[2n]fodd​[n]=x[2n+1]

此时,子序列的索引范围为 n = 0 , 1 , 2 , . . . , N / 2 − 1 n=0,1,2,...,N/2-1 n=0,1,2,...,N/2−1。

步骤 2:DFT 公式的拆分与化简

对 DFT 公式 X [ k ] = ∑ n = 0 N − 1 x [ n ] W N k n ,   k = 0 , 1 , . . . , N − 1 X\left[ k \right]=\sum\limits_{n=0}^{N-1}{x\left[ n \right]W_{N}^{kn}},\ k=0,1,...,N-1 X[k]=n=0∑N−1​x[n]WNkn​, k=0,1,...,N−1 进行拆分,按索引奇偶性将求和项分为两部分:
X [ k ] = ∑ n  为偶数 x [ n ] W N k n + ∑ n  为奇数 x [ n ] W N k n ,   k = 0 , 1 , . . . , N − 1 X\left[ k \right]=\sum\limits_{n \text{ 为偶数}}{x\left[ n \right]W_{N}^{kn}}+\sum\limits_{n \text{ 为奇数}}{x\left[ n \right]W_{N}^{kn}},\ k=0,1,...,N-1 X[k]=n 为偶数∑​x[n]WNkn​+n 为奇数∑​x[n]WNkn​, k=0,1,...,N−1

该拆分过程的基本逻辑为将原求和序列按奇偶索引分离,如下图所示:

在这里插入图片描述

进一步展开可得:
X [ k ] = ∑ m = 0 ( N / 2 ) − 1 x [ 2 m ] W N k ⋅ 2 m + ∑ m = 0 ( N / 2 ) − 1 x [ 2 m + 1 ] W N k ⋅ ( 2 m + 1 ) ,   k = 0 , 1 , . . . , N − 1 X\left[ k \right]=\sum\limits_{m=0}^{(N/2)-1}{x\left[ 2m \right]W_{N}^{k\cdot 2m}}+\sum\limits_{m=0}^{(N/2)-1}{x\left[ 2m+1 \right]W_{N}^{k\cdot \left( 2m+1 \right)}},\ k=0,1,...,N-1 X[k]=m=0∑(N/2)−1​x[2m]WNk⋅2m​+m=0∑(N/2)−1​x[2m+1]WNk⋅(2m+1)​, k=0,1,...,N−1

结合旋转因子的缩放性 W N 2 k m = W N / 2 k m W_N^{2km} = W_{N/2}^{km} WN2km​=WN/2km​,可将上式化简为:
X [ k ] = ∑ m = 0 ( N / 2 ) − 1 f e v e n [ m ] W N / 2 k ⋅ m + W N k ∑ m = 0 ( N / 2 ) − 1 f o d d [ m ] W N / 2 k ⋅ m ,   k = 0 , 1 , . . . , N − 1 X\left[ k \right]=\sum\limits_{m=0}^{(N/2)-1}{f_{even}\left[ m \right]W_{N/2}^{k\cdot m}}+W_{N}^{k}\sum\limits_{m=0}^{(N/2)-1}{f_{odd}\left[ m \right]W_{N/2}^{k\cdot m}},\ k=0,1,...,N-1 X[k]=m=0∑(N/2)−1​feven​[m]WN/2k⋅m​+WNk​m=0∑(N/2)−1​fodd​[m]WN/2k⋅m​, k=0,1,...,N−1

令 F e v e n [ k ] F_{even}[k] Feven​[k] 表示偶索引子序列 f e v e n [ n ] f_{even}[n] feven​[n] 的 DFT 结果, F o d d [ k ] F_{odd}[k] Fodd​[k] 表示奇索引子序列 f o d d [ n ] f_{odd}[n] fodd​[n] 的 DFT 结果,则上式可简化为:
X [ k ] = F e v e n [ k ] + W N k F o d d [ k ] ,   k = 0 , 1 , . . . , N − 1 X\left[ k \right] = F_{even}\left[ k \right] + W_{N}^{k}F_{odd}\left[ k \right],\ k=0,1,...,N-1 X[k]=Feven​[k]+WNk​Fodd​[k], k=0,1,...,N−1

步骤 3:子序列 DFT 结果的周期性分析

F e v e n [ k ] F_{even}[k] Feven​[k] 与 F o d d [ k ] F_{odd}[k] Fodd​[k] 的时域输入长度均为 N / 2 N/2 N/2,但 k k k 的取值范围为 0 , 1 , … , N − 1 0,1,…,N-1 0,1,…,N−1,是输入长度的 2 倍。这表明 F e v e n [ k ] F_{even}[k] Feven​[k] 与 F o d d [ k ] F_{odd}[k] Fodd​[k] 具有周期性特征(可理解为 N N N 个采样点包含了 2 个 2 π 2\pi 2π 周期的频谱采样),即:
F e v e n [ k + N / 2 ] = F e v e n [ k ] F o d d [ k + N / 2 ] = F o d d [ k ] F_{even}\left[ k+N/2 \right] = F_{even}\left[ k \right]\\F_{odd}\left[ k+N/2 \right] = F_{odd}\left[ k \right] Feven​[k+N/2]=Feven​[k]Fodd​[k+N/2]=Fodd​[k]

步骤 4:FFT 递推关系的推导

基于上述周期性,DFT 结果的前半部分可直接表示为:
X [ k ] = F e v e n [ k ] + W N k F o d d [ k ] ,   k = 0 , 1 , . . . , N / 2 − 1 X\left[ k \right] = F_{even}\left[ k \right] + W_{N}^{k}F_{odd}\left[ k \right],\ k=0,1,...,N/2-1 X[k]=Feven​[k]+WNk​Fodd​[k], k=0,1,...,N/2−1

结合旋转因子的对称性 W N k + N / 2 = − W N k W_N^{k+N/2} = -W_N^k WNk+N/2​=−WNk​,DFT 结果的后半部分可推导为:
X [ k + N / 2 ] = F e v e n [ k ] − W N k F o d d [ k ] ,   k = 0 , 1 , . . . , N / 2 − 1 X\left[ k+N/2 \right] = F_{even}\left[ k \right] - W_{N}^{k}F_{odd}\left[ k \right],\ k=0,1,...,N/2-1 X[k+N/2]=Feven​[k]−WNk​Fodd​[k], k=0,1,...,N/2−1

上述推导表明:一个 N N N 点的 DFT 结果可由其奇偶索引子序列的 N / 2 N/2 N/2 点 DFT 结果计算得到。例如,8 点 DFT 可由偶索引 4 点 DFT 结果与奇索引 4 点 DFT 结果推导得出;同理,4 点 DFT 可进一步分解为 2 点 DFT 结果的组合,以此类推,通过分治策略完成整个计算过程。

在这里插入图片描述

四、FFT 计算过程

步骤 1:输入序列的位逆序重排

通过二进制镜像(位逆序)的方式,对时域信号的索引进行二进制编码,并按逆序规则重新排列输入序列,如下表所示(最右侧列为逆序后的计算序列,与前述蝶形计算图对应):

二进制:对应计算序列转换关系原始索引:对应二进制
000: 00: 000
100: 41: 001
010: 22: 010
110: 63: 011
001: 14: 100
101: 55: 101
011: 36: 110
111: 77: 111

步骤 2:蝶形运算的逐级合并

按照奇偶分解的逆过程,从最小的子序列开始,逐级执行蝶形运算,合并奇偶子序列的 DFT 结果,最终得到完整的 N N N 点 FFT 计算结果。

五、补充说明

  1. 离散傅里叶逆变换(IDFT)的计算过程同样可采用上述分治与蝶形运算方法实现,仅需对旋转因子的符号与最终结果进行少量调整。
  2. 本文所阐述的方法为基 2 FFT 算法,除此之外,还存在基 4 等其他类型的 FFT 算法,其详细原理可参考《数字信号处理——原理、算法与应用(第四版)》第 380 页。

总结

  1. FFT 是 DFT 的高效实现方式,依托旋转因子的周期性、对称性、缩放性,结合分治算法降低计算复杂度。
  2. FFT 蝶形计算的逻辑是将 N N N 点 DFT 拆分为奇偶子序列的 N / 2 N/2 N/2 点 DFT 组合,通过递推实现计算简化。
  3. FFT 实际计算需先完成输入序列的位逆序重排,再通过逐级蝶形运算合并子序列结果。

参考文献

Read more

Flutter 三方库 jaguar 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、全能的工业级嵌入式 HTTP 服务端框架与 REST API 交互引擎

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 jaguar 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、透明、全能的工业级嵌入式 HTTP 服务端框架与 REST API 交互引擎 在鸿蒙(OpenHarmony)系统的端侧服务器化、分布式设备互联监控、或者是需要将鸿蒙应用转变为一个能够提供 API 服务的微型网关(如鸿蒙版物联网中枢)场景中,如何通过一套 Dart 代码构建出极致稳健、带路由拦截、支持 Session 且完全透明的 HTTP 服务?jaguar 为开发者提供了一套工业级的、基于生产环境优化的服务端处理方案。本文将深入实战其在鸿蒙端侧服务化中的应用。 前言 什么是 Jaguar?它不是一个普通的 HTTP 监听器,而是一个专为“速度”与“扩展性”

By Ne0inhk
腾讯云 AI 代码助手编程挑战赛 + 构建开发板垃圾图片识别AI对话的Copilot

腾讯云 AI 代码助手编程挑战赛 + 构建开发板垃圾图片识别AI对话的Copilot

一、前言: 最近公司有一个项目需求需要使用到AI智能识别的功能《垃圾智能AI识别系统》,本人一直从事Web领域开发工作,也没接触过人工智能这个赛道,刚好现在借这个“腾讯云 AI 代码助手编程挑战赛”来了解一下AI写代码相关的流程。 刚好也是接触新的技术领域,经过“腾讯云AI代码助手”来帮助我从0到1来实现这个《构建开发板垃圾图片识别AI对话的Copilot》的项目,在很多地方帮助程序员开发人员更好地理解和优化代码,提高软件的可维护性和可靠性、安全性。 上图是通过“腾讯云AI代码助手”从硬件到软件、模型的应用、生成Flask Web API服务,再到最后工作中的最佳实践,通过本人测试了Vue、Js、Python、Go等语言的实际场景,“腾讯云AI代码助手”提供了智能代码补全、单元测试生成、问题修复等多项AI驱动的功能,使开发者能够专注于创造性工作而非繁琐的设置。 【可以来看看我在B站录的一个视屏】: 【腾讯云 AI 代码助手编程挑战赛】+构建开发板垃圾图片识别AI对话的Copilot 在实际使用中,我深刻体验到“腾讯云AI代码助手”的便利,特别是在代码质量的提升方面展

By Ne0inhk

Llama-3.2-3B应用案例:智能客服问答系统搭建指南

Llama-3.2-3B应用案例:智能客服问答系统搭建指南 1. 为什么选Llama-3.2-3B做智能客服? 你可能已经试过不少大模型,但真正用在客服场景里,常常遇到几个现实问题:响应太慢、回答跑题、记不住上下文、部署太重、成本太高。Llama-3.2-3B不是参数堆出来的“巨无霸”,而是Meta专为对话优化的轻量级选手——30亿参数,却在多语言理解、指令遵循和安全对齐上表现扎实。它不追求“全能”,而是专注把一件事做稳:听懂用户问什么,答得准、答得快、答得像人。 更重要的是,它足够“轻”。一台8GB显存的服务器就能跑起来,用Ollama部署,三步完成:拉镜像、启服务、接接口。没有复杂的Docker编排,没有动辄半小时的启动等待,也没有GPU资源争抢。对于中小团队、电商客服、SaaS产品嵌入式助手这类场景,它不是“能用”,而是“好用”“省心”“可维护”。 我们这次不讲理论,

By Ne0inhk

Copilot登录总失败?这7种情况你必须马上检查

第一章:Copilot登录失败的常见现象与影响 GitHub Copilot 作为广受欢迎的AI编程助手,在实际使用过程中,部分开发者频繁遭遇登录失败的问题。这一问题不仅影响编码效率,还可能导致开发流程中断,尤其在团队协作或紧急修复场景下尤为显著。 典型登录失败现象 * 输入凭据后提示“Authentication failed”但账号密码正确 * VS Code 中 Copilot 图标持续显示加载状态,无法完成初始化 * 浏览器重定向至 GitHub 授权页面时卡顿或返回空白页 * 终端输出错误日志:Copilot service is unreachable 对开发工作流的影响 影响维度具体表现编码效率失去代码补全与建议功能,手动编写耗时增加调试体验无法快速生成测试用例或错误解释团队协同新成员因无法启用 Copilot 导致上手速度下降 基础诊断命令 在 VS Code 终端中执行以下命令可获取当前认证状态: # 查看 Copilot 扩展日志 code --log debug # 检查已安装扩展及版本 code --list-extensions

By Ne0inhk