傅里叶变换和拉普拉斯变换

一、回顾欧拉公式

1.1 欧拉公式

欧拉公式为:

它表示单位圆上的一个点。随着 θ 变大,这个复数就在平面上旋转。

例如:

如果取实部:

如果取虚部:

二、傅里叶变换就是频率探针

2.1 案例

假设我们的源信号是:

其含义是:

x(t) = 50Hz 正弦波 + 120Hz 正弦波

其中成分为:

  • 50Hz 分量幅值 = 1
  • 120Hz 分量幅值为 = 0.5

2.2 使用积分计算函数成分

2.2.1 频率探针

可以把傅里叶分析理解成:拿不同频率的波,一个个去和原信号对暗号。

2.2.1 50Hz 积分探针

首先用 50Hz 的波去测试,让它与原信号相乘 (相当于重合的面积相乘),然后在一段时间内积分:

因为 x(t) 原本就有50Hz信号,所以平方永远不小于零,所以会不断累加,结果比较大。

2.2.2 120Hz 积分探针

同样的,我们对 120Hz 也求积分,求他们重合的面积:

2.2.3 计算结果

在下列案例中,引入了实部和虚部的概念。

这是因为我们的案例波形 t=0 时刻开始周期,所以实部统计不到为 0。

为了避免复杂,这里不举例 t=x 时刻开始周期的 f=(t) 函数了。

cpp 复制代码
#include <stdio.h> // 标准输入输出函数
#include <math.h>  // sin、cos、sqrt 数学函数

#define PI 3.14159265358979323846
#define N 100000 // 数值积分分段数量
#define T 1.0    // 信号观察时间,单位:s

// 生成包含 50 Hz 和 120 Hz 的测试信号
double signal(double t)
{
    return sin(2.0 * PI * 50.0 * t) + 0.5 * sin(2.0 * PI * 120.0 * t);
}

// 计算信号在指定频率 f 下的傅里叶积分
void calculate_fourier(double f)
{
    double dt = T / N; // 每个积分小区间的时间宽度
    double real = 0.0; // 傅里叶变换的实部
    double imag = 0.0; // 傅里叶变换的虚部

    // 用矩形面积累加的方式近似计算连续积分
    for (int n = 0; n < N; n++)
    {
        double t = n * dt;               // 当前时刻
        double x = signal(t);            // 当前时刻的信号值
        double angle = 2.0 * PI * f * t; // 检测频率对应的相位角

        real += x * cos(angle) * dt; // 计算实部积分
        imag -= x * sin(angle) * dt; // 计算虚部积分
    }

    // 根据实部和虚部计算复数模长
    double magnitude = sqrt(real * real + imag * imag);

    // 将傅里叶积分模长还原为单边正弦波幅值
    double amplitude = 2.0 * magnitude / T;

    // 输出当前检测频率的计算结果
    printf("检测频率:%6.1f Hz\n", f);
    printf("实部 Re: % .6f\n", real);
    printf("虚部 Im: % .6f\n", imag);
    printf("模长:     %.6f\n", magnitude);
    printf("幅值:     %.6f\n\n", amplitude);
}

int main(void)
{
    // 分别检测 50 Hz、120 Hz 和 80 Hz
    calculate_fourier(50.0);
    calculate_fourier(120.0);
    calculate_fourier(80.0);

    return 0;
}

2.3 引入真正的傅里叶公式

其含义是原信号乘反向旋转频率,然后积分累加。

其中:

就是用来检测频率 f=x(t) 的反向旋转探针。

将 公式展开后得到:

积分后也就是:

将实部分虚部分离可得:

2.4 离散化的 C 代码

离散化代码如下:

cpp 复制代码
#include <stdio.h>
#include <math.h>

#define N 1000                    // 定义采样点数,也就是信号长度为 1000 个点
#define FS 1000.0                 // 定义采样频率,单位为 Hz,这里表示每秒采样 1000 次
#define PI 3.14159265358979323846 // 定义圆周率常量,用于角度计算

int main(void)
{                // 主函数函数体开始
    double x[N]; // 定义长度为 N 的数组,用来保存测试信号的采样值

    // 构造一个测试信号:由 50Hz 正弦波和 120Hz 正弦波叠加而成
    for (int n = 0; n < N; n++)
    {                           
        double t = n / FS;      // 根据采样点序号计算当前时间,单位为秒

        // 给第 n 个采样点赋值生成 50Hz、幅值为 1 的正弦信号叠加 120Hz、幅值为 0.5 的正弦信号
        x[n] = sin(2.0 * PI * 50.0 * t) + 0.5 * sin(2.0 * PI * 120.0 * t);
    } 
    // 对信号 x 进行离散傅里叶变换 DFT,计算频谱
    for (int k = 0; k < N / 2; k++) // 遍历频率下标,只计算前半部分频谱
    {                               // 外层 for 循环函数体开始
        double real = 0.0;          // 保存 DFT 结果的实部,初始值为 0
        double imag = 0.0;          // 保存 DFT 结果的虚部,初始值为 0

        for (int n = 0; n < N; n++)              // 遍历所有采样点,用于计算当前频率 k 的 DFT
        {                                        // 内层 for 循环函数体开始
            double angle = 2.0 * PI * k * n / N; // 计算 DFT 公式中的旋转角度

            real += x[n] * cos(angle); // 累加当前频率分量的实部
            imag -= x[n] * sin(angle); // 累加当前频率分量的虚部,负号来自 DFT 定义
        }

        // 根据实部和虚部计算当前频率分量的幅值
        double amplitude = 2.0 / N * sqrt(real * real + imag * imag); // 计算单边频谱幅值

        // 根据频率下标 k 计算对应的实际频率
        double freq = k * FS / N; // 当前频率点对应的频率,单位为 Hz

        // 只打印幅值比较明显的频率成分
        if (amplitude > 0.1)                                                // 如果当前频率分量的幅值大于 0.1,就认为它比较明显
        {                                                                   // if 语句函数体开始
            printf("freq = %7.2f Hz, amplitude = %.3f\n", freq, amplitude); // 输出频率和幅值
        }
    } 

    return 0;
} 

三、 漏水水桶案例

3.1 漏水水桶案例引入

假设我们有一个漏水的水桶,水量是:

假设规律是:

  • x = 剩余水量

水量的导数是 -2x。

意味着,任意时刻,水量的瞬时减少速率 (每分钟流量),等于当前水量的 2 倍。

假设当前桶中有 1L 水,在不考虑微分的情况,1 分钟后会流出 2L 水。

写成自然常数的形式就是:

  • x0 = 初始水量

3.2 变量分离的微分形式计算

我们假设桶里目前水量为 5L,试求 1 分钟后的桶中水量。

已知水量变化的微分方程为:

把 xxx 和 ttt 分到两边:

按照初始 t=0,x=5 (5L 水) 计算 t = 1 (1 分钟),两边做定积分:

所以:

3.3 自然指数 e 形式计算

四、赫维塞斯算子

4.1 得到算子

首先定义微分算子 (赫维塞斯算子):

那么 px 的意思是:

所以在水桶案例中,可以将原来的导数形式:

写成:

提取可得:

最后得到:

4.2 使用算子

我们知道指数函数满足:

把我们的赫维塞斯算子代入:

因此水量函数一定具有下面的形式:

将我们的初始水量 5L 带入公式,得到:

4.3 总结

这个例子中,把微分直接转化成 p:

于是:

直接变成:

微分方程就像普通代数一样处理了。

五、拉普拉斯变换

5.1 拉普拉斯变换公式

  • x(t) = 时间有关的函数
  • t = 时间
  • = 瞬时变化速度
  • = 拉普拉斯变换符号
  • s = 拉普拉斯域的自变量
  • = 拉普拉斯域的函数
  • = 时间的初始值

可以理解为:

导数的拉普拉斯变换 = s乘原函数的变换结果 − 初始值

5.2 使用拉普拉斯变换计算水桶案例

5.2.1 两侧拉普拉斯变换

水桶案例的原微分方程是:

两边同时进行拉普拉斯变换:

得到:

5.2.2 求 X(s)

提取 X(s):

两侧相除得到水量在 s 域的表达式:

5.2.3 拉普拉斯反变换查表

现在我们需要把拉普拉斯域反变换,目前已有公式:

我们直接将 X(s) 根据公式转换得到:

我们的初始水量是 5L 时间是 1 分钟,代入得到:

5.3 拉普拉斯变换和傅里叶变换的关系

5.3.1 两个公式

傅里叶变换的公式是:

而拉普拉斯变换的公式多了一个 s:

5.3.2 s 的定义

  • = 频率旋转
  • = 指数增长/衰减

5.3.3 两者关系总结

拉普拉斯变换 = 傅里叶变换 + 指数衰减 / 增长因子

在傅里叶分析中,我们只能分析不衰减的波形:

拉普拉斯变换则可以分析增长信号和衰减信号:

这样就是衰减了:

拉普拉斯变换把探针升级了,也就是说,不仅可以分析波形的频率成分,还可以分析衰减状态。

相关推荐
品牌测评6 小时前
Token Plan平台分享|七条算力订阅路径拆解
大数据·人工智能·架构
不会代码的小猴6 小时前
标准模板库(STL)
开发语言·c++·笔记·算法
ZhouDevin6 小时前
算法论文/高效微调4——DoRA:权重分解的低秩适配方法
算法
大模型码小白6 小时前
【AI】一文讲清 RAG:从大模型局限到企业级知识库落地流程
人工智能·深度学习·学习
MomentYY6 小时前
RAG 图检索&多跳推理:有些答案需要“顺藤摸瓜”
人工智能·agent·ai编程
戴维南6 小时前
Ragas核心优势是各种难度的测数据集自动生成,与无标准答案的评测
人工智能
AI探索先锋6 小时前
A* 路径规划:四种算法的进化史-学习
学习·算法
旖旎夜光6 小时前
LeetCode 202:快乐数(双指针问题) —— 题解
数据结构·c++·算法·leetcode·双指针
迪康Defender6 小时前
终端邮件安全全覆盖:规则、关键词、附件白名单配置大全
大数据·人工智能·安全
中电金信7 小时前
中电金信“金融信息技术应用中试平台”入选《智能研发生产力工具选型手册》首批推荐工具
大数据·人工智能