C#中实现FFT的两种方法

2023-11-03

最近工作中有个需求,在C#环境中实现FFT算法,在网上找了些资料,最后实现了下面的两种方式,实际应用任选其一就好。

第一种方法:

不依赖C#中的Complex,需要实现计算过程的每一步详细步骤。

输入序列长度为2的N次幂,使用前需先定义序列长度:

FFT filter = new FFT(256);

filter.fft(x,y) 其中x为实部y为虚部,计算后x为FFT后的实部,y为FFT后的虚部。

 class FFT
    {
        int n, m;
        // Lookup tables. Only need to recompute when size of FFT changes.
        double[] cos;
        double[] sin;

        public FFT(int n)
        {
            this.n = n;
            this.m = (int)(Math.Log(n) / Math.Log(2));

            // Make sure n is a power of 2
            if (n != (1 << m))
                Console.Out.WriteLine("FFT length must be power of 2");

            // precompute tables
            cos = new double[n / 2];
            sin = new double[n / 2];

            for (int i = 0; i < n / 2; i++)
            {
                cos[i] = Math.Cos(-2 * Math.PI * i / n);
                sin[i] = Math.Sin(-2 * Math.PI * i / n);
            }

        }
///x为实部y为虚部///
        private void fft(double[] x, double[] y)
        {
            int i, j, k, n1, n2, a;
            double c, s, t1, t2;

            // Bit-reverse
            j = 0;
            n2 = n / 2;
            for (i = 1; i < n - 1; i++)
            {
                n1 = n2;
                while (j >= n1)
                {
                    j = j - n1;
                    n1 = n1 / 2;
                }
                j = j + n1;

                if (i < j)
                {
                    t1 = x[i];
                    x[i] = x[j];
                    x[j] = t1;
                    t1 = y[i];
                    y[i] = y[j];
                    y[j] = t1;
                }
            }

            // FFT
            n1 = 0;
            n2 = 1;

            for (i = 0; i < m; i++)
            {
                n1 = n2;
                n2 = n2 + n2;
                a = 0;

                for (j = 0; j < n1; j++)
                {
                    c = cos[a];
                    s = sin[a];
                    a += 1 << (m - i - 1);

                    for (k = j; k < n; k = k + n2)
                    {
                        t1 = c * x[k + n1] - s * y[k + n1];
                        t2 = s * x[k + n1] + c * y[k + n1];
                        x[k + n1] = x[k] - t1;
                        y[k + n1] = y[k] - t2;
                        x[k] = x[k] + t1;
                        y[k] = y[k] + t2;
                    }
                }
            }
        }


    }

第二种方式:

傅里叶变换的计算中需要用到复数,无意中发现C#中有复数的定义,考虑使用复数直接计算的方式实现,这样可以利用C#中的复数计算。C#中使用复数需要引用using System.Numerics;

FFT filter = new FFT(256);

filter.DoFFT(x) ; x为输入参数(Complex[]类型),计算后x为FFT后的结果。

突然发现C#好好用啊。。。。。。

class FFT
    {
       
        private Complex[] W;//定义旋转因子

        /// <summary>
        /// 构造函数用于初始化旋转因子。
        /// </summary>
        public FFT(int N)
        {                
            W = initW(N);
        }


        /// <summary>
        /// 快速傅立叶正变换函数
        /// W:输入旋转因子序列数组名
        /// x: 输入信号序列数组名
        /// </summary>
        public void DoFFT(Complex[] x)
        {
            int i = 0, j = 0, k = 0, l = 0;
            Complex up, down, product;
            ReverseOder(x);         ///对输入序列进行倒序
            for (i = 0; i < Math.Log(N, 2); i++)            ///外循环,变换级数循环
            {
                l = 1 << i;
                for (j = 0; j < N; j += 2 * l)             ///中间循环,旋转因子循环
                {
                    for (k = 0; k < l; k++)                     ///内循环,序列循环
                    {
                        product = x[j + k + l] * W[N * k / 2 / l];
                        up = x[j + k] + product;
                        down = x[j + k] - product;
                        x[j + k] = up;
                        x[j + k + l] = down;
                    }
                }
            }
        }

       

        /// <summary>
        /// 倒序函数
        /// W:输入旋转因子序列长度
        /// </summary>
        private Complex[] initW(int N)
        {
            Complex[] W = new Complex[N];
            for (int i = 0; i < N; i++)
            {
                double real = Math.Cos(2 * Math.PI * i / N);        //旋转因子实部展开
                double imag = -1 * Math.Sin(2 * Math.PI * i / N);   //旋转因子虚部展开
                W[i] = new Complex(real, imag);
            }
            return W;
        }


        /// <summary>
        /// ReverseOder()倒序变换
        /// </summary>
        /// <param name="x"></param>
        private void ReverseOder(Complex[] x)
        {
            Complex temp;
            int i = 0, j = 0, k = 0;
            double t;
            for (i = 0; i < N; i++)
            {
                k = i; j = 0;
                t = Math.Log(N, 2);
                while ((t--) > 0)
                {
                    j = j << 1;
                    j |= (k & 1);
                    k = k >> 1;
                }
                if (j > i)
                {
                    temp = x[i];
                    x[i] = x[j];
                    x[j] = temp;
                }
            }
        }


    }

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#中实现FFT的两种方法 的相关文章

  • 在 C# 中创建具有单独列的分隔文本

    我一直在尝试在 C 中创建一个制表符限制的文本文件 以便数据正确显示在单独的列中 Firstname Lastname Age John Smith 17 James Sawyer 31 我尝试过 t 字符 但我得到的只是 Firstnam
  • C++ 中本地类中的静态成员变量?

    我知道我们不能宣布static本地类中的成员变量 但其原因尚不清楚 那么请问有人可以解释一下吗 另外 为什么我们不能访问非static函数内部定义的变量 内部已经定义了局部类 直接在局部类成员函数中 在下面给出的代码中 int main i
  • 如何在 C# 中从 UNIX 纪元时间转换并考虑夏令时?

    我有一个从 unix 纪元时间转换为 NET DateTime 值的函数 public static DateTime FromUnixEpochTime double unixTime DateTime d new DateTime 19
  • 如何为 C 分配的 numpy 数组注册析构函数?

    我想在 C C 中为 numpy 数组分配数字 并将它们作为 numpy 数组传递给 python 我可以做的PyArray SimpleNewFromData http docs scipy org doc numpy reference
  • 如何访问另一个窗体上的ListView控件

    当单击与 ListView 所在表单不同的表单中的按钮时 我试图填充 ListView 我在 Form1 中创建了一个方法以在 Form2 中使用 并将参数传递给 Form1 中的方法 然后填充 ListView 当我调试时 我得到了传递的
  • 用于检查项目文件中的项目变量和引用路径的 api

    我正在研究一个 net application VS2010 与 x 没有 解和变量号这些解决方案中的项目数量 我需要检查项目属性 特定于一定数量的项目 是否同质 并且检查 验证构建期间的参考路径 有没有一个API是这样的吗 如果没有 我该
  • C# Dns.GetHostEntry 不返回连接到 WiFi 的移动设备的名称

    我有一个 C 中的 Windows 窗体应用程序 我试图获取列表中所有客户端的主机名 下面给出的是 ra00l 来自此链接的代码示例 GetHostEntry 非常慢 https stackoverflow com questions 99
  • 使用 C 语言使用 strftime() 获取缩写时区

    我看过this https stackoverflow com questions 34408909 how to get abbreviated timezone and this https stackoverflow com ques
  • Rx 中是否有与 Task.ContinueWith 运算符等效的操作?

    Rx 中是否有与 Task ContinueWith 运算符等效的操作 我正在将 Rx 与 Silverlight 一起使用 我正在使用 FromAsyncPattern 方法进行两个 Web 服务调用 并且我想这样做同步地 var o1
  • PlaySound 可在 Visual Studio 中运行,但不能在独立 exe 中运行

    我正在尝试使用 Visual Studio 在 C 中播放 wav 文件 我将文件 my wav 放入项目目录中并使用代码 PlaySound TEXT my wav NULL SND FILENAME SND SYNC 我按下播放按钮 或
  • 如何使用 watin 中的 FileUploadDialogHandler 访问文件上传对话框

    我正在使用 IE8 和 watin 并尝试通过我的网页测试上传文件 我不能简单地使用 set 方法设置上传文件 例如 ie FileUpload Find ById someId Set C Desktop image jpg 因为上传文本
  • 批量更新 SQL Server C#

    我有一个 270k 行的数据库 带有主键mid和一个名为value 我有一个包含中值和值的文本文件 现在我想更新表格 以便将每个值分配给正确的中间值 我当前的方法是从 C 读取文本文件 并为我读取的每一行更新表中的一行 必须有更快的方法来做
  • Visual Studio 中的测试单独成功,但一组失败

    当我在 Visual Studio 中单独运行测试时 它们都顺利通过 然而 当我同时运行所有这些时 有些通过 有些失败 我尝试在每个测试方法之间暂停 1 秒 但没有成功 有任何想法吗 在此先感谢您的帮助 你们可能有一些共享数据 检查正在使用
  • 上下文敏感与歧义

    我对上下文敏感性和歧义如何相互影响感到困惑 我认为正确的是 歧义 歧义语法会导致使用左推导或右推导构建多个解析树 所有可能的语法都是二义性的语言是二义性语言 例如 C 是一种不明确的语言 因为 x y 总是可以表示两个不同的事物 如下所述
  • 将 log4net 与 Autofac 结合使用

    我正在尝试将 log4net 与 Autofac 一起使用 我粘贴了这段代码http autofac readthedocs org en latest examples log4net html http autofac readthed
  • gcc 的配置选项如何确定默认枚举大小(短或非短)?

    我尝试了一些 gcc 编译器来查看默认枚举大小是否很短 至少一个字节 强制使用 fshort enums 或无短 至少 4 个字节 强制使用 fno short enums user host echo Static assert 4 si
  • Server.MapPath - 给定的物理路径,预期的虚拟路径

    我正在使用这行代码 var files Directory GetFiles Server MapPath E ftproot sales 在文件夹中查找文件 但是我收到错误消息说 给定物理路径但虚拟路径 预期的 我对在 C 中使用 Sys
  • 如何在按钮单击时模拟按键 - Unity

    我对 Unity 中的脚本编写非常陌生 我正在尝试创建一个按钮 一旦单击它就需要模拟按下 F 键 要拾取一个项目 这是我当前的代码 在编写此代码之前我浏览了所有统一论坛 但找不到任何有效的东西 Code using System Colle
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 线程和 fork()。我该如何处理呢? [复制]

    这个问题在这里已经有答案了 可能的重复 多线程程序中的fork https stackoverflow com questions 1235516 fork in multi threaded program 如果我有一个使用 fork 的

随机推荐

  • C++使用PCL注册内存以及释放

    最近测试中发现 电脑运行一定时间就会重启 检查后发现其实是内存被占满了 然后电脑就卡住 这时会有两种情况 重启 把某些程序kill掉释放内存 这个时候不一定会kill那些占很多内存的程序 然后接着查 发现其实就是处理点云的一个程序 注册了内
  • 定时任务Schedule的使用

    定时任务或者说定时调度 是系统中比较普遍的一个功能 例如数据归档 清理 数据定时同步 非实时 定时收发 流量控制等等都需要用到定时任务 常见的定时调度框架有Quartz TBSchedule等 同样 Spring自3 0版本起也增加了任务调
  • 单片机:STM32F4x HAL库软硬SPI驱动ST7735s 1.8寸LCD屏幕

    单片机 STM32F4x HAL库软硬SPI驱动ST7735s 1 8寸LCD屏幕 说明 此篇为学习记录 可能存在错误或者不足 如有问题请指出 硬件环境 主控芯片 STM32F411CEU6 主控开发板 WeAct STM32F411CEU
  • LeetCode 817. 链表组件

    题目链接 https leetcode cn problems linked list components C 代码如下 Definition for singly linked list struct ListNode int val
  • ubuntu16.04中安装NFS服务器

    一 宿主机中对NFS服务的支持 安装相关软件 sudo apt get install nfs kernel server sudo apt get install nfs common 配置NFS服务器 编辑exports sudo vi
  • 数据结构与算法(五):优先队列

    一 基本概念 二 基于数组实现的优先队列 1 基于有序数组的实现 2 基于无序数组的实现 三 基于堆实现的优先队列 1 堆的有序化 2 基于堆实现的优先队列 四 索引优先队列 这节总结一下优先队列的常用实现方法 一 基本概念 普通的队列是一
  • python write函数换行_Python基础知识(三)

    本章小结 学习越往后越意识到总结的重要性 特别是语法基础 东西太多 不用是真的会直接忘掉 我在总结本文的时候就发现 我当时觉得学得很好很扎实 自信不会忘记的东西 真的已经被我忘掉了 还不得不依靠百度来解决问题 这坚定了我更新公众号的决心 f
  • 电调控制直流无刷电机

    实验材料 1 直流无刷电机 A2212 10 KV 1400 2 好盈天行者电调 3 stm32c8t6核心小板 先了解一下无刷电机工作原理 https www bilibili com video av29780856 电机参数 电调参数
  • 亚洲顶级域名.Asia启动注册

    亚洲顶级域名 Asia启动注册 详情到 http ipv1 blog sohu com 64602629 html 优先注册期将于2007年10月开始 并分为三个阶段 第一阶段专为政府机构预留 Asia域名而设 第二阶段让注册商标及服务标记
  • 扎心的前端开发

    喂喂喂 那个切图的 把页面写好就发给研发工程师套模板吧 你好 切图仔 不知道你的团队如何定义前端开发 据我所知 时至今日仍然有很多团队会把前端开发归类为产品或者设计岗位 虽然身份之争多少有些无谓 但我对这种偏见还是心存芥蒂 酝酿了许久 决定
  • Linux 磁盘管理

    参考 Ubuntu 下的磁盘管理 作者 莘莘 发布时间 2021 07 11 17 51 08 网址 https blog csdn net lcx1837 article details 118633544 spm 1001 2014 3
  • Docker之docker镜像容器文件拷贝到宿主主机

    上一篇 Docker之主机拷贝文件到docker镜像容器 介绍了怎么把主机上的文件拷贝到docker容器中 那么如果项目运行之后产生的日志文件 我们希望可以本地查看 那么就需要把产生的日志文件copy到我们本地机器上 来看看具体操作吧 这里
  • Linux运维笔记----时间和时区

    时间和时区 1 系统时间同步 1 1确定时间源地址 同步机IP 222 24 14 61 可以用date命令修改时间 被同步机IP 222 24 14 95 1 2确定客户主机使用的时间同步服务 chronyd service 1 3在ch
  • 多益网络java面试,java全栈工程师面试题

    前言 继续总结吧 没有面试就继续夯实自己的基础 前阵子的在面试过程中遇到的各种问题陆陆续续都会总结出来分享给大家 这次要说的也是面试中被问到的一个高频的问题 我当时其实没答好 因为很早之前是看过springboot启动过程的源码 但是时间隔
  • 以太坊智能合约之如何执行智能合约?

    区块链技术在顶级技术中占据主导地位的主要原因在于其去中心化 虽然区块链的主要目的是在没有中心的情况下维护交易记录 但为了实现自动化 智能合约被引入 那么在写完智能合约之后呢 在本文的这个以太坊智能合约教程中 我们将了解如何使用Truffle
  • 管理信息系统复习总结(保姆级)

    管理信息系统 题型 填空 单选 双选 名词解释 综合 简答 第一章 当今全球商业中的信息系统 1 管理信息系统的新变化 信息技术创新 新的业务模式 电子商务扩张 管理变革 公司和组织变革 2 信息系统如何改变企业 新兴移动数字平台 利用信息
  • Cas服务端5.3.2之开启审计功能(MySQL8)

    1 在cas overlay template的pom里面增加对cas server support audit jdbc的依赖
  • Redis缓存击穿

    什么是缓存击穿 在谈论缓存击穿之前 我们先来回忆下从缓存中加载数据的逻辑 如下图所示 因此 如果黑客每次故意查询一个在缓存内必然不存在的数据 导致每次请求都要去存储层去查询 这样缓存就失去了意义 如果在大流量下数据库可能挂掉 这就是缓存击穿
  • Unity打包浏览器端网页HTML(WebGL)以及部署到Tomcat浏览器访问报错问题解决

    Unity默认打包是PC端客户端程序 想要打包浏览器可以访问的WebGL网页 需要修改一些配置 我使用的Unity版本是2021 3 24f1 1 修改Build Settings 1 1 点击File Build Settings 1 2
  • C#中实现FFT的两种方法

    最近工作中有个需求 在C 环境中实现FFT算法 在网上找了些资料 最后实现了下面的两种方式 实际应用任选其一就好 第一种方法 不依赖C 中的Complex 需要实现计算过程的每一步详细步骤 输入序列长度为2的N次幂 使用前需先定义序列长度