当前位置: 首页 > news >正文

[实战] 基8 FFT/IFFT算法原理与实现(完整C代码)

基8 FFT/IFFT算法原理与实现

文章目录

      • 基8 FFT/IFFT算法原理与实现
        • 数学原理
        • 算法流程
        • C语言实现
        • Python验证脚本
        • 验证方法
        • 关键特性

本文从数学原理开始,不使用任何第三方库,用C语言实现了基于基8的FFT和IFFT算法,效率高,可以移植修改,适合各种场景应用。同时用python验证了C语言实现的正确性,可放心使用。
闲话少说,实战开始:

数学原理

离散傅里叶变换(DFT)定义为:
X[k]=∑n=0N−1x[n]⋅e−j2πkn/N,k=0,1,…,N−1 X[k] = \sum_{n=0}^{N-1} x[n] \cdot e^{-j 2\pi kn/N}, \quad k=0,1,\ldots,N-1 X[k]=n=0N1x[n]ej2πkn/N,k=0,1,,N1
逆变换(IDFT)为:
x[n]=1N∑k=0N−1X[k]⋅ej2πkn/N,n=0,1,…,N−1 x[n] = \frac{1}{N} \sum_{k=0}^{N-1} X[k] \cdot e^{j 2\pi kn/N}, \quad n=0,1,\ldots,N-1 x[n]=N1k=0N1X[k]ej2πkn/N,n=0,1,,N1

基8算法要求N=8mN=8^mN=8m。将输入序列分解为8个子序列:
xr[m]=x[8m+r],r=0,1,…,7; m=0,1,…,N/8−1 x_r[m] = x[8m + r], \quad r=0,1,\ldots,7; \ m=0,1,\ldots,N/8-1 xr[m]=x[8m+r],r=0,1,,7; m=0,1,,N/81

DFT可表示为:
X[k]=∑r=07WNrk⋅DFT{xr[m]}[kmod  (N/8)] X[k] = \sum_{r=0}^{7} W_N^{rk} \cdot DFT\{x_r[m]\}[k \mod (N/8)] X[k]=r=07WNrkDFT{xr[m]}[kmod(N/8)]
其中WN=e−j2π/NW_N = e^{-j2\pi/N}WN=ej2π/N为旋转因子。

算法流程
  1. 位反转置换:将输入序列按8进制位反转顺序重排
  2. 蝶形运算:分log⁡8N\log_8 Nlog8N级迭代:
    • sss级处理N/8sN/8^sN/8s个8点组
    • 每组应用8点DFT矩阵运算
    • 乘以旋转因子WNrkW_N^{rk}WNrkrrr=子序列索引,kkk=频率索引)
  3. IFFT处理:FFT结果取共轭→执行FFT→取共轭→除以NNN
C语言实现
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>typedef float real;
typedef struct { real real, imag; } complex;#define PI 3.14159265358979323846f// 复数运算
complex cmplx(real r, real i) { return (complex){r, i}; }
complex cadd(complex a, complex b) { return cmplx(a.real+b.real, a.imag+b.imag); }
complex csub(complex a, complex b) { return cmplx(a.real-b.real, a.imag-b.imag); }
complex cmul(complex a, complex b) {return cmplx(a.real*b.real - a.imag*b.imag, a.real*b.imag + a.imag*b.real);
}// 位反转置换 (基8)
void bit_reverse(complex *x, int N) {int m = (int)(logf(N)/logf(8) + 0.5f);complex *temp = malloc(N * sizeof(complex));for (int i = 0; i < N; i++) {int rev = 0, n = i;for (int j = 0; j < m; j++) {rev = (rev << 3) | (n & 7);n >>= 3;}temp[rev] = x[i];}for (int i = 0; i < N; i++) x[i] = temp[i];free(temp);
}// 8点DFT核函数
void dft8(complex *x) {complex temp[8];for (int k = 0; k < 8; k++) {temp[k] = cmplx(0, 0);for (int n = 0; n < 8; n++) {real angle = -2*PI*k*n/8;complex w = cmplx(cosf(angle), sinf(angle));temp[k] = cadd(temp[k], cmul(x[n], w));}}for (int i = 0; i < 8; i++) x[i] = temp[i];
}// 基8 FFT
void fft_base8(complex *x, int N) {bit_reverse(x, N);int stages = (int)(logf(N)/logf(8));for (int stage = 0; stage < stages; stage++) {int group_size = 1;for (int i = 0; i <= stage; i++) group_size *= 8;int half_group = group_size / 8;for (int group = 0; group < N; group += group_size) {for (int pos = 0; pos < half_group; pos++) {complex data[8];// 加载数据并应用旋转因子for (int r = 0; r < 8; r++) {int idx = group + r*half_group + pos;real angle = -2*PI*r*pos/(group_size);complex w = cmplx(cosf(angle), sinf(angle));data[r] = cmul(x[idx], w);}// 执行8点DFTdft8(data);// 存储结果for (int r = 0; r < 8; r++) {x[group + r*half_group + pos] = data[r];}}}}
}// 基8 IFFT
void ifft_base8(complex *x, int N) {// 取共轭for (int i = 0; i < N; i++) x[i].imag = -x[i].imag;fft_base8(x, N);// 取共轭并缩放real scale = 1.0f/N;for (int i = 0; i < N; i++) {x[i].real *= scale;x[i].imag = -x[i].imag * scale;}
}// 文件操作
void save_bin(const char *fname, complex *data, int N) {FILE *f = fopen(fname, "wb");fwrite(data, sizeof(complex), N, f);fclose(f);
}void load_bin(const char *fname, complex *data, int N) {FILE *f = fopen(fname, "rb");fread(data, sizeof(complex), N, f);fclose(f);
}int main() {const int N = 64;  // 8^2=64complex input[N], fft_out[N], ifft_out[N];// 生成测试信号: 2个正弦波叠加for (int i = 0; i < N; i++) {real t = 2*PI*i/N;input[i] = cmplx(sinf(3*t) + 0.5f*cosf(7*t), 0);}// 保存输入数据save_bin("input_c.bin", input, N);// 执行FFTfor (int i = 0; i < N; i++) fft_out[i] = input[i];fft_base8(fft_out, N);save_bin("fft_c.bin", fft_out, N);// 执行IFFTfor (int i = 0; i < N; i++) ifft_out[i] = fft_out[i];ifft_base8(ifft_out, N);save_bin("ifft_c.bin", ifft_out, N);return 0;
}
Python验证脚本
import numpy as np
import matplotlib.pyplot as pltdef read_bin(fname, n):return np.fromfile(fname, dtype=np.complex64, count=n)def compare(data1, data2, name):diff = np.abs(data1 - data2)print(f"{name} 最大误差: {np.max(diff):.6e}")plt.figure()plt.plot(diff, 'r-')plt.title(f"{name}误差分析")plt.ylabel("误差幅度")plt.xlabel("采样点")plt.grid()plt.savefig(f"{name}_diff.png")N = 64# 读取C语言生成的数据
input_c = read_bin("input_c.bin", N)
fft_c = read_bin("fft_c.bin", N)
ifft_c = read_bin("ifft_c.bin", N)# 使用NumPy计算参考值
fft_ref = np.fft.fft(input_c)
ifft_ref = np.fft.ifft(fft_ref)# 结果对比
compare(fft_c, fft_ref, "FFT")
compare(ifft_c, ifft_ref, "IFFT")
compare(ifft_c, input_c, "IFFT_原始信号")# 保存参考结果
fft_ref.astype(np.complex64).tofile("fft_py.bin")
ifft_ref.astype(np.complex64).tofile("ifft_py.bin")
验证方法
  1. 数据生成

    • C程序生成测试信号并保存为input_c.bin
    • 执行FFT保存为fft_c.bin
    • 执行IFFT保存为ifft_c.bin
  2. Python验证

    • 读取C生成的二进制文件
    • 使用NumPy计算FFT/IFFT作为参考
    • 计算并报告最大误差
    • 生成误差分析图

FFT结果:
在这里插入图片描述
IFFT结果:
在这里插入图片描述
IFFT原始数据:
在这里插入图片描述

  1. 误差分析
     FFT 最大误差: 6.492365e-05 平均误差:4.865580e-06IFFT 最大误差: 1.459477e-06 平均误差:6.917030e-07IFFT_原始信号 最大误差: 1.513257e-06 平均误差:6.714861e-07
    
    误差主要来源于浮点精度差异,在可接受范围内
关键特性
  1. 原位计算:FFT/IFFT均原位操作减少内存占用
  2. 精确位反转:8进制位反转确保正确数据访问模式
  3. 模块化设计:8点DFT作为独立核函数
  4. 完整流程:包含数据生成→变换→存储→验证全流程

此实现完整展示了基8 FFT算法的原理和实现,并通过严格的数值验证确保了正确性。


注意:因为基8算法的特性,本文代码只能计算8^(2n)点数的FFT和IFFT


研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)



文章转载自:
http://chromhidrosis.wkuuf.cn
http://bitten.wkuuf.cn
http://anhemitonic.wkuuf.cn
http://cake.wkuuf.cn
http://amen.wkuuf.cn
http://anaesthetize.wkuuf.cn
http://anilide.wkuuf.cn
http://carlsruhe.wkuuf.cn
http://cantonment.wkuuf.cn
http://chloritize.wkuuf.cn
http://chaussure.wkuuf.cn
http://babesiosis.wkuuf.cn
http://cete.wkuuf.cn
http://censorship.wkuuf.cn
http://accidently.wkuuf.cn
http://barotolerance.wkuuf.cn
http://bourride.wkuuf.cn
http://calvary.wkuuf.cn
http://atonal.wkuuf.cn
http://borne.wkuuf.cn
http://carelessly.wkuuf.cn
http://ceremony.wkuuf.cn
http://allometric.wkuuf.cn
http://binominal.wkuuf.cn
http://butcherly.wkuuf.cn
http://aerify.wkuuf.cn
http://bacteriochlorophyll.wkuuf.cn
http://caulescent.wkuuf.cn
http://aminoplast.wkuuf.cn
http://calycinal.wkuuf.cn
http://www.dtcms.com/a/280857.html

相关文章:

  • 【每天一个知识点】多模态信息(Multimodal Information)
  • 【知识扫盲】tokenizer.json中的vocab和merges是什么?
  • 【机器学习】第二章 Python入门
  • 【Unity】MiniGame编辑器小游戏(十四)基础支持模块(游戏窗口、游戏对象、物理系统、动画系统、射线检测)
  • 数学中的教学思想
  • MySQL 8.0 OCP 1Z0-908 题目解析(24)
  • P3842 [TJOI2007] 线段
  • Sharding-JDBC 分布式事务实战指南:XA/Seata 方案解析
  • sqli-labs靶场通关笔记:第18-19关 HTTP头部注入
  • 【C++】初识C++(1)
  • 课题学习笔记1——文本问答与信息抽取关键技术研究论文阅读(用于无结构化文本问答的文本生成技术)
  • Java 大视界 -- Java 大数据机器学习模型在金融风险传染路径分析与防控策略制定中的应用(347)
  • QT——QList的详细讲解
  • Redis的下载安装+基础操作+redis客户端的安装
  • 使用 1Panel PHP 运行环境部署 WordPress
  • 辨析git reset三种模式以及和git revert的区别:回退到指定版本和撤销指定版本的操作
  • 零样本轴承故障诊断SC - GAN模型
  • 【PCIe 总线及设备入门学习专栏 5.1.2 -- PCIe EP core_rst_n 与 app_rst_n】
  • React-router
  • 未来大模型在中小型企业如何实现普及
  • PG备份一(逻辑备份)
  • Kafka——生产者消息分区机制原理剖析
  • Java基础教程(009): Java 的封装
  • Samba配置使用
  • 算法学习笔记:23.贪心算法之活动选择问题 ——从原理到实战,涵盖 LeetCode 与考研 408 例题
  • 重学前端005 --- 响应式网页设计 CSS 盒子模型
  • Python函数进阶
  • python 基于 httpx 的流式请求
  • 封装---统一处理接口与打印错误信息
  • Linux下调试器gdb/cgdb的使用