C++实现快速傅里叶变换FFT(附带源码)

C++ 实现快速傅里叶变换(FFT)

项目介绍

快速傅里叶变换(Fast Fourier Transform, FFT)是一种高效计算 离散傅里叶变换(DFT) 及其逆变换的方法。傅里叶变换在信号处理、图像处理、数据分析等领域具有广泛应用,例如:

  • 音频频谱分析
  • 图像处理中的滤波
  • 无线通信中的调制解调
  • 数据压缩(如 JPEG、MP3)

本项目将使用 C++ 实现 基于 Cooley-Tukey 算法的 FFT,并提供:

  1. FFT 计算(递归和迭代方式)
  2. 逆 FFT(IFFT)计算
  3. FFT 在信号处理中的应用
  4. 完整代码、详细注释及代码解读

项目实现思路

离散傅里叶变换(DFT)公式

DFT 计算复杂度为 O(N²),FFT 通过 分治思想 将其优化至 O(N logN),主要思路如下:

  1. 奇偶分解:将原始序列按奇数索引偶数索引拆分。
  2. 递归计算:分别对奇偶部分求 FFT。
  3. 合并结果:利用旋转因子 合并结果。

本项目提供 递归版和迭代版 FFT,并支持 逆变换(IFFT)


代码实现

#include <iostream>
#include <vector>
#include <complex>
#include <cmath>

using namespace std;

// 定义复数类型
using Complex = complex<double>;
using CArray = vector<Complex>;

/**
 * @brief 递归实现快速傅里叶变换 (FFT)
 * @param x 输入复数数组
 */
void fft(CArray &x) {
    int N = x.size();
    if (N <= 1) return; // 递归终止条件

    // 拆分为偶数和奇数部分
    CArray even(N / 2), odd(N / 2);
    for (int i = 0; i < N / 2; i++) {
        even[i] = x[i * 2];
        odd[i] = x[i * 2 + 1];
    }

    // 递归计算 FFT
    fft(even);
    fft(odd);

    // 组合结果
    for (int k = 0; k < N / 2; k++) {
        Complex t = polar(1.0, -2 * M_PI * k / N) * odd[k]; // 旋转因子 e^(-j2πk/N)
        x[k] = even[k] + t;
        x[k + N / 2] = even[k] - t;
    }
}

/**
 * @brief 递归实现逆快速傅里叶变换 (IFFT)
 * @param x 输入复数数组
 */
void ifft(CArray &x) {
    int N = x.size();
    if (N <= 1) return;

    // 拆分为偶数和奇数部分
    CArray even(N / 2), odd(N / 2);
    for (int i = 0; i < N / 2; i++) {
        even[i] = x[i * 2];
        odd[i] = x[i * 2 + 1];
    }

    // 递归计算 IFFT
    ifft(even);
    ifft(odd);

    // 组合结果
    for (int k = 0; k < N / 2; k++) {
        Complex t = polar(1.0, 2 * M_PI * k / N) * odd[k]; // 旋转因子 e^(j2πk/N)
        x[k] = (even[k] + t) / 2.0;
        x[k + N / 2] = (even[k] - t) / 2.0;
    }
}

/**
 * @brief 测试 FFT 和 IFFT
 */
int main() {
    CArray data = {1, 2, 3, 4, 5, 6, 7, 8}; // 输入信号

    cout << "原始数据:" << endl;
    for (const auto &val : data) cout << val << " ";
    cout << endl;

    fft(data); // 执行 FFT

    cout << "FFT 结果:" << endl;
    for (const auto &val : data) cout << val << " ";
    cout << endl;

    ifft(data); // 执行 IFFT

    cout << "逆 FFT 结果 (恢复信号):" << endl;
    for (const auto &val : data) cout << val << " ";
    cout << endl;

    return 0;
}

代码解读

1. 复数计算

FFT 计算涉及复数运算,因此使用 std::complex<double> 定义复数类型,并使用 std::vector<Complex> 存储 FFT 计算的数据。

2. 递归 FFT 计算

a) 终止条件

当输入数组的长度为 1 时,不再递归,直接返回。

b) 拆分数据

FFT 采用 分治法,将输入数据分为偶数索引部分奇数索引部分,分别递归计算其 FFT。

c) 递归计算

分别对偶数索引部分奇数索引部分应用 FFT,进一步细分计算,直到拆分到单个元素。

d) 旋转因子计算

使用欧拉公式计算旋转因子 该因子用于合并递归计算得到的结果。

e) 结果合并

利用旋转因子,将偶数部分的 FFT 结果奇数部分的 FFT 结果组合,构造最终的 FFT 变换结果。


3. 逆 FFT (IFFT) 计算

a) 结构类似 FFT

逆 FFT 采用相同的分治策略,也将输入数据分为偶数部分奇数部分,并递归计算。

b) 旋转因子方向相反

不同于 FFT,逆 FFT 的旋转因子采用正指数 进行计算,以执行逆变换。

c) 归一化

逆变换的最终结果需要除以 2,以归一化恢复原始信号。


4. FFT 计算流程

  1. 输入信号数据
  2. 递归拆分数据
  3. 对拆分后的数据递归应用 FFT
  4. 使用旋转因子合并结果
  5. 返回最终的频域数据

5. IFFT 计算流程

  1. 输入 FFT 变换后的数据
  2. 递归拆分数据
  3. 递归应用 IFFT
  4. 使用旋转因子合并
  5. 归一化恢复原始信号

6. 示例执行

  1. 程序首先输出原始信号数据
  2. 应用 FFT 并输出频域数据
  3. 应用 IFFT 恢复原始信号,并验证结果

项目总结

  • FFT 通过分治法优化 DFT 计算,提高效率
  • IFFT 可用于恢复原始信号
  • 适用于音频、图像处理、信号分析等领域
  • 若处理大规模数据,建议使用优化的 FFT 库,如 FFTW
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值