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

2024-08-30 14:36

本文主要是介绍C#实现快速傅里叶变换(FFT),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、FFT类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;namespace DFT_FFTApp.Utils
{public class FFT{/// <summary>/// FFT/// </summary>/// <param name="xL"></param>/// <returns></returns>public static double[] ButterflyFFT(List<double> xL){int len = xL.Count;if (len == 0){return null;}double[] data_r = new double[len];double[] data_i = new double[len];for (int i = 0; i < len; i++){data_r[i] = xL[i];}double[] fft_r = new double[data_r.Length];double[] fft_i = new double[data_r.Length];double[] result = new double[data_r.Length];BF_FFT(ref data_r, ref data_i, ref fft_r, ref fft_i);GetMod(ref fft_r, ref fft_i, ref result);return result;}/// <summary>/// FFT算法/// </summary>/// <param name="data_r"></param>/// <param name="data_i"></param>/// <param name="result_r"></param>/// <param name="result_i"></param>public static void BF_FFT(ref double[] data_r, ref double[] data_i, ref double[] result_r, ref double[] result_i){if (data_r.Length == 0 || data_i.Length == 0 || data_r.Length != data_i.Length)return;int len = data_r.Length;double[] X_r = new double[len];double[] X_i = new double[len];for (int i = 0; i < len; i++)//将源数据复制副本,避免影响源数据的安全性{X_r[i] = data_r[i];X_i[i] = data_i[i];}DataSort(ref X_r, ref X_i);//位置重排double WN_r, WN_i;//旋转因子int M = (int)(Math.Log(len) / Math.Log(2));//蝶形图级数for (int l = 0; l < M; l++){int space = (int)Math.Pow(2, l);int num = space;//旋转因子个数double temp1_r, temp1_i, temp2_r, temp2_i;for (int i = 0; i < num; i++){int p = (int)Math.Pow(2, M - 1 - l);//同一旋转因子有p个蝶WN_r = Math.Cos(2 * Math.PI / len * p * i);WN_i = -Math.Sin(2 * Math.PI / len * p * i);for (int j = 0, n = i; j < p; j++, n += (int)Math.Pow(2, l + 1)){temp1_r = X_r[n];temp1_i = X_i[n];temp2_r = X_r[n + space];temp2_i = X_i[n + space];//为蝶形的两个输入数据作副本,对副本进行计算,避免数据被修改后参加下一次计算X_r[n] = temp1_r + temp2_r * WN_r - temp2_i * WN_i;X_i[n] = temp1_i + temp2_i * WN_r + temp2_r * WN_i;X_r[n + space] = temp1_r - temp2_r * WN_r + temp2_i * WN_i;X_i[n + space] = temp1_i - temp2_i * WN_r - temp2_r * WN_i;}}}result_r = X_r;result_i = X_i;}/// <summary>/// 对原数据组进行重排/// </summary>/// <param name="data_r"></param>/// <param name="data_i"></param>public static void DataSort(ref double[] data_r, ref double[] data_i){if (data_r.Length == 0 || data_i.Length == 0 || data_r.Length != data_i.Length)return;int len = data_r.Length;int[] count = new int[len];int M = (int)(Math.Log(len) / Math.Log(2));double[] temp_r = new double[len];double[] temp_i = new double[len];for (int i = 0; i < len; i++){temp_r[i] = data_r[i];temp_i[i] = data_i[i];}for (int l = 0; l < M; l++){int space = (int)Math.Pow(2, l);int add = (int)Math.Pow(2, M - l - 1);for (int i = 0; i < len; i++){if ((i / space) % 2 != 0)count[i] += add;}}for (int i = 0; i < len; i++){data_r[i] = temp_r[count[i]];data_i[i] = temp_i[count[i]];}}/// <summary>/// 求模/// </summary>/// <param name="complex_r"></param>/// <param name="complex_i"></param>/// <param name="mod"></param>public static void GetMod(ref double[] complex_r, ref double[] complex_i, ref double[] mod){if (complex_r.Length == 0 || complex_i.Length == 0 || complex_r.Length != complex_i.Length)return;for (int i = 0; i < complex_r.Length; i++)mod[i] = Math.Sqrt(complex_r[i] * complex_r[i] + complex_i[i] * complex_i[i]);}}
}

2、应用

private void DFTInitialize(){List<double> list = GetCaseData(128);double[] res = FFT.ButterflyFFT(list);foreach (double item in res){Console.WriteLine(item);}easyChartX1.Plot(res, 0, 1);}/// <summary>/// 获取时域数据/// </summary>/// <param name="points"></param>/// <returns></returns>private List<double> GetCaseData(int points){List<double> data = new List<double>();double w = 2*Math.PI / points;for(int i = 0; i < points;i++){double d=Math.Sin(w * i);//Console.WriteLine($"i={i},d={d.ToString("G2")}");data.Add(d);}return data;}

这篇关于C#实现快速傅里叶变换(FFT)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1121101

相关文章

springboot filter实现请求响应全链路拦截

《springbootfilter实现请求响应全链路拦截》这篇文章主要为大家详细介绍了SpringBoot如何结合Filter同时拦截请求和响应,从而实现​​日志采集自动化,感兴趣的小伙伴可以跟随小... 目录一、为什么你需要这个过滤器?​​​二、核心实现:一个Filter搞定双向数据流​​​​三、完整代码

SpringBoot利用@Validated注解优雅实现参数校验

《SpringBoot利用@Validated注解优雅实现参数校验》在开发Web应用时,用户输入的合法性校验是保障系统稳定性的基础,​SpringBoot的@Validated注解提供了一种更优雅的解... 目录​一、为什么需要参数校验二、Validated 的核心用法​1. 基础校验2. php分组校验3

Python实现AVIF图片与其他图片格式间的批量转换

《Python实现AVIF图片与其他图片格式间的批量转换》这篇文章主要为大家详细介绍了如何使用Pillow库实现AVIF与其他格式的相互转换,即将AVIF转换为常见的格式,比如JPG或PNG,需要的小... 目录环境配置1.将单个 AVIF 图片转换为 JPG 和 PNG2.批量转换目录下所有 AVIF 图

Pydantic中model_validator的实现

《Pydantic中model_validator的实现》本文主要介绍了Pydantic中model_validator的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录引言基础知识创建 Pydantic 模型使用 model_validator 装饰器高级用法mo

AJAX请求上传下载进度监控实现方式

《AJAX请求上传下载进度监控实现方式》在日常Web开发中,AJAX(AsynchronousJavaScriptandXML)被广泛用于异步请求数据,而无需刷新整个页面,:本文主要介绍AJAX请... 目录1. 前言2. 基于XMLHttpRequest的进度监控2.1 基础版文件上传监控2.2 增强版多

Redis分片集群的实现

《Redis分片集群的实现》Redis分片集群是一种将Redis数据库分散到多个节点上的方式,以提供更高的性能和可伸缩性,本文主要介绍了Redis分片集群的实现,具有一定的参考价值,感兴趣的可以了解一... 目录1. Redis Cluster的核心概念哈希槽(Hash Slots)主从复制与故障转移2.

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.

Mybatis 传参与排序模糊查询功能实现

《Mybatis传参与排序模糊查询功能实现》:本文主要介绍Mybatis传参与排序模糊查询功能实现,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、#{ }和${ }传参的区别二、排序三、like查询四、数据库连接池五、mysql 开发企业规范一、#{ }和${ }传参的

Docker镜像修改hosts及dockerfile修改hosts文件的实现方式

《Docker镜像修改hosts及dockerfile修改hosts文件的实现方式》:本文主要介绍Docker镜像修改hosts及dockerfile修改hosts文件的实现方式,具有很好的参考价... 目录docker镜像修改hosts及dockerfile修改hosts文件准备 dockerfile 文