离散傅里叶变换(DFT)的推导及C语言实现

news2024/9/27 7:16:13

1、傅里叶变换(FT)

傅里叶变换(连续时间傅里叶变换)是该部分内容的理论基础,回顾一下:

傅里叶变换:

        F(\omega ) = \int_{-\infty }^{+\infty}f(t)e^{-j\omega t}dt

傅里叶逆变换:

        f(t ) = \frac{1}{2\pi }\int_{-\infty }^{+\infty}F(\omega )e^{j\omega t}d\omega

以上是连续时间傅里叶变换,但计算机只能处理离散的数据。因此有了离散傅里叶变换(DFT),下面进行详细推导。


2、离散傅里叶变换(DFT)

2.1 采样和离散时间傅里叶变换(DTFT)

使用采样可将连续域上的数据离散化。信号学科里面使用冲激序列串来对连续信号采样。

有信号f(t),现对其采样。若采样频率为 f_{s},则采样间隔 T_{s} = \frac{1}{f_{s}} ,用以采样的冲激序列串定义为:

        \delta_{s}(t) = \sum_{n=-\infty}^{+\infty}\delta(t-nT_{s})

因此采样后的信号为:

        f_{s}(t)=\sum_{n=-\infty}^{+\infty}f(t)\delta(t-nT_{s})

此时将采样后信号 f_{s}(t) 代入傅里叶变换公式:

        F_s(\omega ) = \int_{-\infty }^{+\infty}\left [ \sum_{n=-\infty}^{+\infty}f(t)\delta(t-nT_{s}) \right ]e^{-j\omega t}dt

交换积分与求和次序:

        F_s(\omega ) = \sum_{n=-\infty}^{+\infty}\int_{-\infty }^{+\infty}f(t)\delta(t-nT_{s})e^{-j\omega t}dt

由 \delta (t) 函数的筛选性 \int_{-\infty}^{+\infty}x(t)\delta (t-t_0{})dt=x(t_0),将上式中 f(t)e^{-j\omega t} 看成x(t), 得到离散时间傅里叶变换(DTFT)

        F_s(\omega ) = \sum_{n=-\infty}^{+\infty}f(nT_{s})e^{-j\omega nT_s}

因为 nT_{s} 表示采样的时间点,所以可令 k = nT_{s},因此离散时间傅里叶变换的更一般形式为:

        F_s(\omega ) = \sum_{k=-\infty}^{+\infty}f(k)e^{-j\omega k}


2.2 离散傅里叶变换(DFT)

2.1中通过采样使得信号在时域离散化,但并不能保证其频域也离散化,同样不利于计算机处理。

由性质:时域离散,频域周期化;频域离散,时域周期化。因此若想让信号在频域也离散,则需要该信号在时域上为周期信号。

但原信号不一定为周期信号。解决方式是周期延拓:截取原无限长信号的N个采样点,假设:

N个采样点为原信号的一个周期;

  

② N个采样点外为该N点的周期延拓。

 

这样原先的离散非周期信号就变成离散周期信号,因此频域得以离散化。

在上述周期延拓的基础上,假设采样间隔为 T_{s} ,则N个采样点的采样周期 T_{0}=NT_{s},从连续信号f(t)中截取的N个采样点的信号可表示为:

        x(t) = \sum_{n=0}^{N-1}f(t)\delta (t-nT_s)

因为周期延拓,x(t)为是周期信号,周期函数的傅里叶级数为:​ 

        F(k\omega)=\frac{1}{T}\int_{0}^{T}f(t)e^{-jk\omega t}dt 

x(t)代入其中,得:

        X(k\omega)=\frac{1}{T_0}\int_{0}^{T_0}\left [ \sum_{n=0}^{N-1}f(t)\delta (t-nT_s) \right ]e^{-jk\omega_{}t}dt

交换积分与求和次序:

        X(k\omega)=\frac{1}{T_0}\sum_{n=0}^{N-1}\int_{0}^{T_0} f(t)\delta (t-nT_s) e^{-jk\omega_{}t}dt

同理,由 \delta (t) 函数的筛选性,上式变为:

        X(k\omega)=\frac{1}{T_0}\sum_{n=0}^{N-1}f(nT_s)e^{-jk\omega nT_s}

因为T_{0}=NT_{s}\omega =\frac{2\pi }{T0}=\frac{2\pi }{NT_{s}},代入上式:

        X(k\omega)=\frac{1}{NT_{s}}\sum_{n=0}^{N-1}f(nT_s)e^{-j\frac{2\pi }{N} kn}

x[n]=f(nT_s)X(k\omega)T_s=X[k],得离散傅里叶变换(DFT)的表达式为:

        X[k]=\sum_{n=0}^{N-1}x[n]e^{-j\frac{2\pi }{N} kn},  0\leq k< N 且 k\in Z

离散傅里叶逆变换(IDFT)的表达式为:

        x[n]=\frac{1}{N}\sum_{n=0}^{N-1}X[k]e^{j\frac{2\pi }{N} kn}

注意:为了满足正逆变换的自洽,\frac{1}{N}放在正逆变换其中之一前就可以,通常放在逆变换前。

补充:令W_{N}^{kn}=e^{-j\frac{2\pi }{N} kn},则:

        X[k]=\sum_{n=0}^{N-1}x[n]W_{N}^{kn}


2.3 离散傅里叶变换(DFT)的C语言实现

根据上述推导出的公式,很容易编码实现。如下:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define PI 3.1415927

double realComput(double xn[], int ndft, int k);
double imageComput(double xn[], int ndft, int k);

typedef struct {
	double real;
	double image;
} Complex;

void dft(double x[], int ndft) {
	Complex* dftRes = (Complex*)malloc(ndft * sizeof(Complex));
	if (dftRes == NULL) {
		return;
	}

	for (int i = 0; i < ndft; ++i) {
		dftRes[i].real = realComput(x, ndft, i);
		dftRes[i].image = imageComput(x, ndft, i);
		printf("%lf + %lfi\n", dftRes[i].real, dftRes[i].image);
	}

	free(dftRes);
}

double realComput(double xn[], int ndft, int k) {
	double realPart = 0;
	for (int i = 0; i < ndft; ++i) {
		realPart += xn[i] * cos(2 * PI / ndft * k * i);
	}
	return realPart;
}

double imageComput(double xn[], int ndft, int k) {
	double imagePart = 0;
	for (int i = 0; i < ndft; ++i) {
		imagePart -= xn[i] * sin(2 * PI / ndft * k * i);
	}
	return imagePart;
}

int main() {
	double xn[9] = {1,2,3,4,5,0,0,0,85};
	dft(xn, sizeof(xn) / sizeof(double));
	system("pause");
	return 0;
}

运行结果:

暂未发现问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1078780.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

practical on mifare

抽象的。 mifare Classic 是市场上使用最广泛的非接触式智能卡。 其设计和实施细节由制造商保密。 本文研究了该卡的体系结构以及卡与读卡器之间的通信协议。 然后&#xff0c;它提供了一种实用的、低成本的攻击&#xff0c;可以从卡的内存中恢复秘密信息。 由于伪随机生成器的…

计算32位二进制整数中1的个数(包括负数补码)

引言&#xff1a; 在计算机科学和编程中&#xff0c;位操作是一项重要的技能。一个常见的任务是计算一个32位二进制整数中1的个数&#xff0c;包括负数的补码表示。这个问题有多种解决方法&#xff0c;本博客将介绍一种高效的解决方案&#xff0c;同时提供详细的代码案例。 背…

“优化STM32单片机处理大量网络数据的方法“

"优化STM32单片机处理大量网络数据的方法" 在处理大量网络数据时&#xff0c;对STM32单片机的裸机程序&#xff0c;可采用以下处理方法&#xff1a;1.使用DMA实现直接内存访问&#xff0c;减轻CPU负担。2.优化缓冲区管理&#xff0c;使用循环缓冲区或多缓冲区。3.利…

智能垃圾桶在线监测方案

提高垃圾收集率、减少乱丢垃圾是我们共同努力的目标&#xff0c;在人口稠密的城市&#xff0c;垃圾是必要的服务&#xff0c;在许多城市&#xff0c;垃圾车是空的&#xff0c;垃圾随处可见沿线&#xff0c;但它不是有效的方法&#xff0c;因为有很多空间可以很多垃圾离开的路上…

Java Agent之ByteBuddy

1&#xff1a;前言 在上一篇文章介绍 Java Agent 技术时&#xff0c;结合 Byte Buddy 技术实现了统计方法执行时间的功能。本次分享深入介绍 Byte Buddy 的一些基础知识&#xff0c;SkyWalking Agent 强大的地方就是重度使用该工具实现探针数据动态生成代码填充参数的。 2&am…

基于springboot实现在线动漫信息交流分享平台项目【项目源码+论文说明】

基于springboot实现在线动漫信息交流分享平台演示 摘要 随着社会互联网技术的快速发展&#xff0c;每个行业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于在线动漫信息平台当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xf…

公司文件防泄密软件——「天锐绿盾」@德人合科技

天锐绿盾是一款企业级数据安全解决方案&#xff0c;主要用于保护企业的知识产权、客户资料、财务数据、技术图纸、应用系统等机密信息化数据不外泄。 PC访问地址&#xff1a; &#x1f517;isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 该软件解决方案…

Three.js如何计算3DObject的2D包围框?

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 在Three.js应用开发中&#xff0c;有时你可能需要为3D场景中的网格绘制2D的包围框&#xff0c;应该怎么做&#xff1f; 朴素的想法是把网格的3D包围框投影到屏幕空间&#xff0c;例如&#xff0c;下图中的绿色框 3D包围框…

Linux 部署1Panel 现代化运维管理面板进行公网远程访问

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《速学数据结构》 《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言1. Linux 安装1Panel2. 安装cpolar内网穿透2.1 使用一键脚本安装命令 2.2向系统添加服务2.3 启动cpolar服务…

【名城优企游学】国轩高科,用数字化带来强劲发展动力

成立于2006 年5月&#xff0c;系中国动力电池产业最早进入资本市场的民族企业&#xff1b;2015年5月上市&#xff0c;股票代码SZ.002074&#xff0c;拥有新能源汽车动力锂电池、储能、输配电设备等业务板块&#xff0c;建有独立成熟的研发、采购、生产、销售体系。 它就是新能…

五分钟了解一下什么是「贪心算法 」‼️‼️‼️

五分钟了解一下什么是「贪心算法 」‼️‼️‼️ 1 概念 贪心的意思在于在作出选择时&#xff0c;每次都要选择对自身最为有利的结果&#xff0c;保证自身利益的最大化。贪心算法就是利用这种贪心思想而得出一种算法。 贪心算法作为五大算法之一&#xff0c;在数据结构中的应…

如何进行lidar和imu的外参标定

我们使用的lidar_align这个算法来进行标定。 1.下载源码 在ros工作空间下的src文件夹下运行这个命令。 git clone https://github.com/ethz-asl/lidar_align.gitsudo apt-get install libnlopt-devcd ..catkin_make 这里编译的时候会爆一些错误。我遇到的是&#xff1a; 这…

渗透测试成功的8个关键

渗透测试 (penetration test)并没有一个标准的定义&#xff0c;国外一些安全组织达成共识的通用说法是&#xff1a;渗透测试是通过模拟恶意黑客的攻击方法&#xff0c;来评估计算机网络系统安全的一种评估方法。这个过程包括对系统的任何弱点、技术缺陷或漏洞的主动分析&#x…

考试中心|学习资料|学习情况|纯净无广|在线组卷刷题

土著刷题Plus专业版v1.2版本已全面对其个人版功能&#xff0c;完全满足学员培训/刷题考察全套流程&#xff0c;提供完整的服务流程。接下来将主要介绍一下这一版的新功能 考试中心 满足培训机构/刷题组织者考察刷题用户的管理需求&#xff0c;【围绕考试展开】&#xff0c;提供…

SQLite数据库使用时碰到的问题

背景 1、最近使用sqlite数据库&#xff0c;因为轻量&#xff0c;所以&#xff0c;不需要特别的部署服务器环境。 开发的平台使用的是Qt 碰到的问题 1、我在向数据库中插入字段的时候&#xff0c;少写了一个字段的内容&#xff0c;报这个错误 QSqlError("", "…

火焰原子吸收光谱法、容量法和电感耦合等离子体发射光谱法

声明 本文是学习GB-T 1871.5-2022 磷矿石和磷精矿中氧化镁含量的测定 火焰原子吸收光谱法、容量法和电感耦合等离子体发射光谱法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本文件描述了在磷矿石和磷精矿中测定氧化镁含量的火焰原子吸收…

史上最全 结构型模式之 代理 适配器 装饰者 模式

创建型设计模式 原型模式 建造者模式 创建者模式对比_软工菜鸡的博客-CSDN博客 5&#xff0c;结构型模式 day03 结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式&#xff0c;前者采用继承机制来组织接口和类&#xff0c;后者釆用组…

大模型部署手记(8)LLaMa2+Windows+llama.cpp+英文文本补齐

1.简介&#xff1a; 组织机构&#xff1a;Meta&#xff08;Facebook&#xff09; 代码仓&#xff1a;https://github.com/facebookresearch/llama 模型&#xff1a;llama-2-7b 下载&#xff1a;使用download.sh下载 硬件环境&#xff1a;暗影精灵7Plus Windows版本&#…

制药企业纯化水设备的应用及维护:设备健康管理软件的关键作用

纯化水设备在制药企业中扮演着重要角色&#xff0c;为生产高纯度水提供支持。然而&#xff0c;为了确保设备的可靠性和稳定性&#xff0c;有效的维护和管理至关重要。设备健康管理软件PreMaint成为实现这一目标的关键工具。本文将介绍PreMaint软件如何优化纯化水设备的维护&…

Qt_C++读写FM1208 CPU卡源码、支持windows、Linux系统

本示例使用的发卡器&#xff1a; Android Linux RFID读写器NFC发卡器WEB可编程NDEF文本/智能海报/-淘宝网 (taobao.com) #include "mainwindow.h" #include "./ui_mainwindow.h" #include <QDebug> #include "QLibrary" #include "Q…