简介《信号与系统》实验五信号的分解与合成是一份配套课程实验的完整报告面向电子信息类本科生及信号处理入门者用于理解傅里叶分解、谐波提取与信号重构的核心方法。压缩包内仅1个docx文档约589KB内容按实验流程组织包含方波与三角波从基波到五次谐波的分解记录、合成波形对比、示波器测量结果以及各次谐波相位差调整后的合成效果说明。已有447人学习下载资源实用性强。报告系统总结了有源带通滤波器作为选频网络提取各次谐波的原理明确合成信号时须按傅里叶级数系数调整各分量幅度与相位方能逼近原信号同时还对比了方波与三角波频谱成分的差异。无论是实验预习、报告撰写还是复习傅里叶变换与信号频谱分析都可直接参考。1. 信号与系统实验里分解与合成到底在验证什么做过信号与系统实验的人多半有这种体验一个方波在示波器上棱角分明可一旦把它展开成傅里叶级数再用有限项正弦波叠加回去边缘处总会出现那个甩不掉的过冲。理论上说谐波项数越多过冲宽度越窄可它的峰值却始终不降——这就是吉布斯现象也是「信号的分解与合成」这个实验最值得细看的地方。这个实验表面上只是把一个周期信号拆开再拼回去实际检验的是三件事第一你是否理解正交函数集为什么能作为分解的基底第二你是否掌握了傅里叶系数的数值求法而不是只会套教材公式第三你能否解释截断带来的误差——包括吉布斯过冲、频谱泄漏和混叠。对正在做课设的学生来说这是把《信号与系统》从公式变成代码的第一道坎对已经工作的工程师这个实验的底层逻辑直接对应着频谱分析仪的读数方式、滤波器设计的频率响应计算以及一切基于DFT的工具的内在误差来源。本文不打算复述教材而是按「数学前提 → 最小可运行代码 → 参数陷阱 → 验证方法」的顺序把整个实验从理解到落地完整走一遍。2. 分解与合成背后的两个数学前提2.1 正交性为什么分解结果是唯一的把一个信号分解成一系列基本分量的和最核心的问题是你凭什么说拆出来的这几项是对的如果可以用任意波形做基底那同一个方波既能拆成正弦波的叠加也能拆成三角波的叠加结果就不唯一。正交性解决了这个问题——当基底函数两两正交时每个分量的系数独立于其他分量也就是说求某个系数的积分过程会自动屏蔽掉其他分量的贡献。对于周期为 T 的信号 x(t)傅里叶级数使用的基底是 {e^{j n ω0 t}}其中 ω0 2π/T。这些复指数函数在任意一个周期内满足正交关系∫_0^T e^{j m ω0 t} · (e^{j n ω0 t})* dt Tm n 时否则为 0这里 (·)* 表示共轭。这个性质带来的工程意义很直接你计算第 n 次谐波的系数时不需要关心其他谐波长什么样直接做一次积分就能得到唯一答案。这也是为什么信号与系统课程里优先讲傅里叶展开而不是其他分解方式——正弦函数是线性时不变系统的特征函数一个复指数信号通过LTI系统后只会改变幅度和相位频率不变。这个「频率不变」性质是频谱分析、滤波、调制三大应用的共同根基。2.2 从连续积分到离散求和数值计算的落点理论推导时傅里叶系数写起来很干净c_n (1/T) ∫_0^T x(t) e^{-j n ω0 t} dt合成公式是 x(t) Σ_{n-∞}^{∞} c_n e^{j n ω0 t}。但实验里拿到的信号是采样后的离散序列连续积分必须改成离散近似。最常见做法就是用 numpy 的梯形积分函数 trapz把积分变成求和。这里有一个容易被忽略的点离散化之后谐波次数 n 的取值范围不是无限的。采样率 fs 决定了你能正确表示的最高频率是 fs/2奈奎斯特频率因此 n 的有效范围大约是 [-fs/(2f0), fs/(2f0)]。如果实验中设置的谐波次数超过这个范围你合成的信号里会出现一种假象——高频分量被「折叠」回低频区域这就是混叠。后面第4章会专门讲这个问题此处先记住一个结论分解项数 N 不是越大越好它受采样率的硬约束。2.3 三个参数对分解结果的直接影响这个实验一共就三个参数信号周期 T、采样率 fs、谐波次数 N。它们各自的角色如下表参数作用设置不当的后果建议取值T周期决定基波频率 f0 1/T所有谐波频率都是 f0 的整数倍非整数周期截断会造成频谱泄漏取采样点数的约数保证采到整数个周期fs采样率决定可表示的最高频率 fs/2过低则高次谐波混叠波形明显失真fs ≥ 10 × N × f0留足余量N谐波次数决定合成精度N 越大越接近原信号过小则边缘模糊、细节丢失从 1 开始逐次翻倍观察误差变化趋势实际操作中我一般先把 T 设为 1 秒fs 设为 1000 Hz这样采样点数恰好是 1000画图和计算都方便。N 从 1 推到 50 左右既能看清误差递减趋势又不会让计算量变大到影响交互。下一章就按这组参数写最小代码。3. 用 Python 复现信号的分解与合成实验3.1 最小代码一个三角波从分解到重建实验对象选三角波——它比方波少一个吉布斯过冲的干扰因素三角波的傅里叶系数按 1/n² 衰减收敛快更适合先验证流程正确性而方波那种 1/n 衰减带来的慢收敛问题放到第 4 章单独讨论。下面这段代码用 numpy 完成系数计算和信号重建全程不依赖 scipy只要环境里有 numpy 和 matplotlib 就能跑。import numpy as np import matplotlib.pyplot as plt # 1. 参数设置 T 1.0 # 周期 [s] fs 1000 # 采样率 [Hz] N 20 # 合成时保留的谐波次数包含正负频率 t np.arange(0, T, 1/fs) # 一个周期内的时间序列 # 2. 生成原始三角波信号范围 [-1, 1] x 2 * np.abs(2 * (t / T - np.floor(t / T 0.5))) - 1 # 3. 分解用梯形积分求前 N 次谐波的复系数 c_n c np.zeros(2 * N 1, dtypecomplex) for n in range(-N, N 1): c[n N] np.trapz(x * np.exp(-2j * np.pi * n * t / T), t) / T # 4. 合成用系数重建信号 x_recon np.zeros_like(t) for n in range(-N, N 1): x_recon c[n N] * np.exp(2j * np.pi * n * t / T) x_recon np.real(x_recon) # 理论结果应为实数取实部消除浮点误差 # 5. 对比原始信号和重建信号 plt.figure(figsize(10, 4)) plt.plot(t, x, labeloriginal, linewidth2) plt.plot(t, x_recon, --, labelfN{N}, alpha0.8) plt.legend() plt.xlabel(time [s]) plt.ylabel(amplitude) plt.title(Signal Decomposition and Reconstruction) plt.grid(True) plt.show()这段代码的核心在第三步np.trapz(x * np.exp(-2j * np.pi * n * t / T), t) / T正是傅里叶系数公式的离散实现。exp(-2j * np.pi * n * t / T)是基函数 e^{-j n ω0 t}其中 ω0 2π/T与信号逐点相乘后梯形积分近似了连续积分最后除以 T 完成归一化。第四步是反向操作把每个系数乘回对应的正频率基函数累加得到重建信号。值得注意的细节循环里用的是负 n 到正 n 的双边形式因为复指数基函数在正负频率上成对出现。虽然原始信号是实信号系数满足共轭对称c_{-n} c_n^*但为了保持数值精度和代码可读性我通常保留完整双边形式而不是只算正频率再乘 2——后者容易在手工处理时丢掉相位信息。3.2 从频谱图判断分解是否正确信号重建了还不够你得确认每个系数 c_n 的幅值是否符合理论预期。以三角波为例理论上的傅里叶系数幅值按 1/n² 衰减且只存在奇次谐波——偶次谐波系数应该接近 0但不等于 0因为数值积分有微小误差。下面这段代码画出系数幅值谱帮你做这一步验证freqs np.arange(-N, N 1) / T # 各谐波对应的频率 mag np.abs(c) # 取复数系数幅值 plt.figure(figsize(10, 3)) plt.stem(freqs, mag, basefmt ) plt.xlabel(frequency [Hz]) plt.ylabel(|c_n|) plt.title(Fourier Coefficients of Triangular Wave) plt.grid(True, alpha0.3) plt.show() # 检查偶次谐波系数是否近似为 0 even_indices np.arange(2, N 1, 2) N # 对应 n -N..N 中偶数的位置 print(max |c_n| at even harmonics:, np.max(np.abs(c[even_indices])))这段代码用 stem 画离散谱线因为傅里叶系数是离散值连线图会误导视觉。检查偶次谐波系数的逻辑是三角波理论谱中偶次分量应为零如果输出结果大于 1e-3 量级说明信号生成本身有偏——常见原因是 t 的取值没有严格覆盖一个整周期或者三角波公式里相位偏移导致波形不对称。数值积分导致的误差通常在 1e-6 量级如果某个偶次分量异常大优先检查原始信号的生成而不是傅里叶系数的计算。3.3 改两个参数观察误差随 N 的变化分解与合成实验最有说服力的部分是误差曲线把 N 分别设为 1、2、5、10、20、50计算每个 N 下重建信号与原始信号的均方根误差再看误差随 N 的下降趋势。对于三角波误差应该按 1/N² 左右的速度衰减——这是由系数衰减率决定的。N_list [1, 2, 5, 10, 20, 50] err [] for Nk in N_list: # 复用前面分解合成的逻辑这里简写为直接调用 ck np.zeros(2 * Nk 1, dtypecomplex) for n in range(-Nk, Nk 1): ck[n Nk] np.trapz(x * np.exp(-2j * np.pi * n * t / T), t) / T xk np.zeros_like(t) for n in range(-Nk, Nk 1): xk ck[n Nk] * np.exp(2j * np.pi * n * t / T) err.append(np.sqrt(np.mean((x - np.real(xk)) ** 2))) for Nk, e in zip(N_list, err): print(fN{Nk:3d}, RMSE{e:.6f})运行后你会看到典型结果N1 时误差在 0.1 量级N20 时降到 1e-3 量级N50 时接近 1e-4 量级。如果误差曲线衰减速度明显偏慢比如 N 翻倍但误差只降了不到一半说明信号里有间断点方波或者采样率不够高次谐波被混叠破坏了。误差曲线的斜率本身就是判断实验状态的一个有效指标——这个话题第 4 章继续展开。4. 采样率、截断长度与吉布斯现象三个影响合成质量的真实因素4.1 混叠谐波次数超过 fs/2 时会发生什么实验做到一半你可能会遇到一种诡异的情况N 从 20 增加到 50重建信号不但没更接近原始信号某些位置反而出现了明显的波浪形失真。这不是代码写错了而是混叠——当谐波频率 n·f0 超过 fs/2 时这个分量会以 fs/2 为对称轴折叠回低频区域叠加到真实低频分量上产生一个看似合理但完全错误的波形。举例理解fs 1000 Hz 时奈奎斯特频率是 500 Hz。基波 1 Hz 的信号第 600 次谐波频率是 600 Hz折叠后变成 1000 - 600 400 Hz这个分量会被错误地当作 400 Hz 信号参与合成。如果只看到时域波形你很难察觉这一点因为折叠后的分量排列在错误的频率位置上波形整体仍然平滑。判断混叠是否发生有一个简单办法把 N 设到理论最大值的两倍观察重建误差是否不降反升。对于刚才的三角波例子理论最大值是 fs/(2f0) 500N 超过 500 后误差必然恶化。实际操作时我一般留出至少 5 倍余量fs ≥ 10 × N × f0。这样既能保证高次谐波落在可表示范围内又能避免谐波频率恰好落在奈奎斯特频率附近时的边界效应。如果实验框架限制采样率不可调那就要反过来限制 N 的上限——这个约束关系值得在实验报告里明确写出来它体现了采样定理在具体实验中的约束。4.2 吉布斯现象收敛不意味着逼近方波的傅里叶系数按 1/n 衰减比三角波的 1/n² 慢得多这带来一个典型现象合成波形在间断点两侧出现过冲且这个过冲的峰值不随 N 增大而降低只会在宽度上越来越窄。这就是吉布斯现象数值上约为跳变幅度的 8.95%。很多学生第一次看到这个现象时第一反应是代码有 bug。实际上这恰恰是傅里叶级数收敛性质的直接体现——傅里叶级数在间断点处收敛到左右极限的平均值而过冲本身是截断误差的固有特征。用方波替换第 3 章的三角波你把 N 从 10 调到 500过冲峰值几乎不变但过冲的宽度会越来越窄最终在视觉上「消失」——因为人眼的分辨率有限窄到一定程度就看不清了。处理这个问题的常见做法有两种一是接受过冲的存在在实验报告里明确记录过冲百分比并与理论值 8.95% 对比二是引入窗函数或 σ 因子通过修改傅里叶系数的幅值来抑制过冲比如 Lanczos σ 修正但这会让合成信号的整体频谱发生偏移属于代价换效果的做法一般不在基础实验里展开。我的建议是实验报告里同时呈现无修正和有修正的结果用证据说明吉布斯现象的来源是截断而非算法错误。4.3 频谱泄漏当采样长度不是整数倍周期第 2 章参数表里有一条建议「T 取采样点数的约数保证采到整数个周期」。实际做实验时不少人直接从采集设备里拿一段数据长度未必恰好覆盖整周期。此时 DFT 会隐式地把这段数据当成一个完整周期来周期延拓如果首尾不连续延拓后的信号在边界处人为引入了一个跳变频谱上表现为能量从真实频率向两侧扩散这就是频谱泄漏。处理办法有两个层面的选择。第一个层面如果实验允许控制信号源那就严格同步采样确保截取长度等于周期的整数倍并验证首尾采样值接近相等。第二个层面如果数据已经采回来了长度不可改那就用窗函数汉宁窗、汉明窗对数据做加权换取主瓣展宽但旁瓣大幅降低的效果。对于分解与合成这个实验正确做法是前者——你既然自己生成信号就应该保证整数周期截取窗函数是频谱分析课程的内容放在这里反而混淆了实验的核心逻辑。这节内容与「信号与系统考研」复习时的考点直接相关频谱泄漏和吉布斯现象经常作为简答题出现区别在于泄漏源于非整周期截断吉布斯现象源于有限项截断。前者是采样数据的问题后者是级数收敛的问题。至少在大理大学等高校的信号与系统考研真题中这个区分经常被拿来考察概念理解。5. 用帕塞瓦尔定理验证你的分解结果是否可信5.1 能量守恒一个可量化的验收标准前面所有验证都是定性或间接的最后这一步给出可精确数字化的验证方案——帕塞瓦尔定理。它说的是信号在时域的总能量等于频域各分量能量之和。对于周期信号这个关系写作(1/T) ∫_0^T |x(t)|² dt Σ_{n-∞}^{∞} |c_n|²验证代码很简单在原有参数基础上加两行E_time np.mean(x ** 2) # 时域平均功率 E_freq np.sum(np.abs(c) ** 2) # 频域各谐波功率之和 print(ftime domain: {E_time:.10f}) print(ffreq domain: {E_freq:.10f}) print(fenergy error: {abs(E_time - E_freq):.2e})只要采样率足够、周期截取正确两者的相对误差应该在 1e-12 到 1e-14 量级——这个量级取决于浮点数精度而不是计算方法的准确度。如果误差在 1e-6 量级说明梯形积分的步长过大需要提高 fs如果误差出现在 1e-3 量级说明周期截取有偏差采样数据不完整。与第 3 章的 RMSE 指标相比帕塞瓦尔验证有个独特的优势它不需要重建信号就能判断分解正确性直接对比频谱系数和时域能量即可。这意味着你可以在 N 设置得很小的时候就发现数据问题而不必等到合成阶段才看到波形失真。实际上我用这个方法排查过很多次实验数据异常——大多数时候问题不在傅里叶计算而在信号生成或截取环节。5.2 残差能量与 N 的量化关系帕塞瓦尔定理还提供了另一个有用的分析手段把无穷级数的总能量拆成「已保留部分」和「截断部分」。用 N 次谐波合成时残差能量可以精确表示为E_residual E_time - Σ_{n-N}^{N} |c_n|²这个残差对应着前面实验中的 RMSE 平方是理论值和实测误差之间的桥梁。三角波的系数按 1/n² 衰减所以残差能量按 1/N³ 量级递减方波的系数按 1/n 衰减残差能量只按 1/N 量级递减。在代码里算一下不同 N 下的残差能量再和 RMSE 的平方对比你会发现两个数字完全吻合——因为它们本质上是同一个量的两种表现形式。把这个规律写进实验报告的结论部分比单纯贴重建波形图更有说服力。比较理想的呈现方式是一张双对数坐标下的误差曲线图横轴为 N纵轴为残差能量三角波的曲线斜率为 -3方波的斜率为 -1两条曲线的斜率差异直观地展示了信号光滑程度与傅里叶系数衰减速度的关系。5.3 把这套验证方法固化为实验模板到这里整个实验的完整流程可以固化为一个可复用的模板生成信号 → 计算傅里叶系数 → 帕塞瓦尔校验能量一致性 → 用不同 N 合成并计算 RMSE → 记录残差能量与 N 的变化关系。这套流程不仅适用于三角波和方波直接换掉信号生成公式就可以处理锯齿波、半波整流波形、脉冲串等任何周期信号。做实验报告时把 N 1、3、5、10、20、50 六组数据整理成表附上帕塞瓦尔校验的误差值和残差能量曲线分析部分的素材就足够扎实了——比放十张时域对比图更能体现对分解与合成原理的理解深度。本文还有配套的精品资源点击获取