Appearance
复变函数与积分变换(可选)
概念
先说清楚一个误会:复数不是"数学家的游戏",它是工程上最省事的记账方式。
它的起源很朴素:x² = -1 没有实数解,于是规定 i² = -1。 但真正的威力在于几何解释:
z = re^{i\theta} 读作:"把长度放大 r 倍,再逆时针转 \theta 角"。 于是"复数乘法"就是"两个动作的复合"——模相乘、角相加。 这一句话解释了复数的全部运算规则。
为什么 elec 与 auto 离不开它:
| 场景 | 复数在做什么 |
|---|---|
| 正弦稳态分析(相量法) | A cos(ωt+φ) 写成 A e^{jφ}——把"带相位的正弦"变成"一个复数" |
| 阻抗 | Z = R + jX——电感的 jωL 与电容的 1/(jωC) 让"微分方程"变成"代数除法" |
| 滤波器与频谱 | 傅里叶变换把"卷积"变成"乘法" |
| 系统稳定性 | "极点落在左半平面(连续)或单位圆内(离散)" |
| 数字信号处理 | Z 变换 + z^{-1} 表示单位延迟 |
⚠️ 本篇是可选篇,但它是
elec的直接前置:README 第四节把elec(信号与系统、DSP、通信原理)标为"分支、非前置"——它不在"由硅到 C"这条链上,但要走这条路,复变与积分变换是绕不过的第一道门。
本篇在主线上的位置:它是
math的最后一篇,也是一次"收线"——把math/10的微分方程、math/11的特征值、math/20的谱半径,全部归结到同一句话上:极点(特征根)的位置决定系统的行为。
原理
一、复数:四种表示与"乘法即旋转"
同一个复数的四种写法:
| 形式 | 写法 | 适合做什么 |
|---|---|---|
| 代数式 | z = a + b i | 加减法 |
| 几何式 | 复平面上的点 (a, b) | 理解"旋转" |
| 三角式 | z = r(\cos\theta + i\sin\theta) | 连接几何与代数 |
| 指数式 | z = r e^{i\theta} | 乘除、幂、开方(最好用) |
其中 r = |z| = √(a²+b²),θ = arg z(辐角),a = r cos θ,b = r sin θ。
欧拉公式(整个复变函数的枢纽):
怎么理解它:把 e^{iθ} 按 math/10-calculus.md 的泰勒展开写开——
"i² = -1 让每两项并成一组,实部正好是 cos 的展开,虚部正好是 sin 的展开。" 例 2 会把这条级数真跑一遍给你看。
两个必须背的推论:
"三角函数是指数函数的线性组合"——这就是"正弦信号在 LTI 系统里形状不变"的根本原因(因为指数函数是指数函数的特征函数)。
乘法的几何意义(本节最值钱的一条):
| 运算 | 几何动作 | 代数含义 |
|---|---|---|
乘 i | 逆时针转 90° | i² = -1 就是"转两次 90° = 转 180° = 取负" |
| 除 | 模相除、角相减 | 1/i = -i |
乘方 z^n | 角乘 n | (re^{iθ})^n = r^n e^{in\theta}(棣莫弗公式) |
共轭 z̄ = a − bi | 关于实轴镜像 | z·z̄ = ∣z∣²(实数) |
"乘
i就是转 90°"这一条值得单独记住:(1+i)^8 = 16就是"从 45° 出发转 8 次 45°(共 360°)回到正实轴,模从√2涨到2⁴ = 16"——例 1 会把它算出来。
二、复变函数:解析、极点与留数
复变函数 w = f(z):输入一个复数,输出一个复数——从几何上看,它是"把复平面上的图形映射成另一个图形"。
可导(在复变里叫解析 / 全纯)的条件苛刻得多:f = u + iv 在一点可导,必须满足柯西-黎曼方程:
柯西-黎曼方程带来的三个"神奇"后果:
| 后果 | 说明 |
|---|---|
| 解析则无穷次可导 | 实变里做不到——C¹ 不代表 C²;复变里一次可导就够了 |
| 实部虚部都是调和函数 | ∂²u/∂x² + ∂²u/∂y² = 0——这就是电路里的"电势满足拉普拉斯方程" |
| 积分与路径无关 | 留数定理的根基(在有奇点的情况下,积分只由"包围了哪些奇点"决定) |
奇点、极点与留数:
| 概念 | 含义 |
|---|---|
| 奇点 | f 不解析的点 |
m 阶极点 | f(z) 在奇点附近像 1/(z−z₀)^m 那样发散 |
| 留数 | 极点处展开里 1/(z−z₀) 那一项的系数 |
| 留数定理 | 闭合回路的积分 = 2πi × 所围留数之和 |
这一节在工程上的用处,只有一个词:极点位置。 因为在
elec/auto里,"系统函数"通常是一个有理函数H(s) = N(s)/D(s)——D(s) = 0的根就是极点,极点的位置直接决定系统是稳定、振荡还是发散。 后面四、五两节都在用这一个结论。
三、傅里叶变换:时域 ↔ 频域
从傅里叶级数到傅里叶变换:周期信号可以分解成"基频的整数倍";非周期信号把周期看作无穷大,离散的谐波就变成连续的频谱:
四个必记的变换对:
时域 f(t) | 频域 F(ω) | 用途 |
|---|---|---|
δ(t)(冲激) | 1(全频段等幅) | 理想测试信号 |
1(直流) | 2πδ(ω) | 只在 0 频有能量 |
e^{-at}u(t)(a>0) | 1/(a + iω) | 一阶系统的频率响应 |
矩形脉冲(宽 T) | T·sinc(ωT/2) | 带宽与脉宽成反比 |
四条最重要的性质:
| 性质 | 形式 | 工程含义 |
|---|---|---|
| 线性 | af + bg ↔ aF + bG | 叠加原理 |
| 时移 → 相移 | f(t−t₀) ↔ F(ω)e^{-iωt₀} | 延迟不改变幅度谱,只改相位 |
| 卷积 → 相乘 | f * g ↔ F(ω)·G(ω) | ★ 最值钱的一条:时域卷积 = 频域相乘 |
| 帕塞瓦尔 | ∫∣f∣²dt = (1/2π)∫∣F∣²dω | 能量守恒(换个坐标轴算能量) |
"卷积 → 相乘"为什么最值钱:因为滤波器就是一个卷积(输出 = 输入 * 冲激响应)——有了它,设计滤波器只要"在频域上乘一个形状";计算上还能用 FFT 把 O(n²) 的卷积降到 O(n log n)。 例 3 会用离散傅里叶变换把这条性质验一遍。
采样定理(回链 elec/13-sampling.md):采样频率必须大于信号最高频率的 2 倍,否则频谱会发生混叠——"2f_max"这个数,就是"频域复制品不重叠"的临界条件。
四、拉普拉斯变换:把微分方程变成代数方程
定义(s = σ + iω 是复频率):
它比傅里叶变换多了一个实部 σ——好处是"能让更多信号收敛"(比如 e^{at} 在傅里叶下不收敛,在拉普拉斯下只要 σ > a 就收敛)。代价是要考虑收敛域(ROC)。
性质表(前三条是解微分方程的钥匙):
| 性质 | 形式 |
|---|---|
| 线性 | af + bg ↔ aF + bG |
| 微分 | f'(t) ↔ sF(s) − f(0⁻) |
| 积分 | ∫f ↔ F(s)/s |
| 时移 | f(t−t₀)u(t−t₀) ↔ F(s)e^{-st₀} |
| 卷积 | f * g ↔ F(s)·G(s) |
| 初值 / 终值定理 | f(0⁺) = lim_{s→∞} sF(s);f(∞) = lim_{s→0} sF(s) |
"微分变成了乘 s"——这就是"微分方程变代数方程"的全部秘密。
用它解一阶 RC 电路(与 math/10-calculus.md 例 5 对照):
| 步 | 操作 |
|---|---|
| 1 | 时域方程:RC·dv/dt + v = V_S(v(0) = 0) |
| 2 | 拉普拉斯变换(用微分性质):RC[sV(s) − 0] + V(s) = V_S/s |
| 3 | 代数整理:V(s) = V_S / [s(1 + sRC)] |
| 4 | 部分分式:V(s) = V_S[1/s − 1/(s + 1/RC)] |
| 5 | 查表逆变换:v(t) = V_S(1 − e^{−t/RC}) ✔ |
同一件事,两条路:math/10 用"分离变量 + 积分",这里用"查表 + 代数"。 后者对高阶系统才显示威力——因为"解微分方程"变成了"分解有理函数"。
稳定性判据(把全篇串起来):
五、Z 变换:离散版的一句话
定义:X(z) = Σ_{n=0}^{∞} x[n] z^{-n};与拉普拉斯的关系是 z = e^{sT}(T 是采样周期)。
| 连续 | 离散 |
|---|---|
s 平面 | z 平面 |
左半平面(Re s < 0) | 单位圆内(∣z∣ < 1) |
e^{-st} 的延迟 | z^{-1}(单位延迟,硬件里就是一个寄存器) |
| 极点决定稳定性 | 极点决定稳定性 |
数字滤波器就写成 H(z) = Y(z)/X(z)——"z^{-1} 是延迟一拍"这一条,让滤波器直接对应到硬件上的寄存器与乘法器(这正是 embed 里 DSP 实现的起点)。
六、复变与积分变换在主线的落点
| 落点 | 用什么 |
|---|---|
circuit 正弦稳态/阻抗 | 相量(复数)与 jωL、1/(jωC) |
elec 信号与系统 | 傅里叶、拉普拉斯、卷积定理 |
elec 数字信号处理 | Z 变换、DFT/FFT |
elec 通信原理 | 频谱、带宽、调制(频移 = 乘 e^{iω₀t}) |
auto 稳定性 | 极点位置(左半平面 / 单位圆内) |
mus/art 数字音频与图像 | 采样、频谱、DCT(傅里叶的表亲) |
示例
例 1:复数的四则运算与"乘 i 就是转 90°"
python
import cmath, math, unicodedata
def w(s):
return sum(2 if unicodedata.east_asian_width(c) in "WF" else 1 for c in s)
def pad(s, n):
return s + " " * max(0, n - w(s))
def fmt(z):
return "%.6f %+.6fi" % (z.real, z.imag)
z = complex(1, 1)
print("=== ① 四种表示 ===")
print(" 代数式 z = %.4f + %.4fi" % (z.real, z.imag))
print(" 模 |z| = √(1²+1²) = √2 = %.10f" % abs(z))
print(" 辐角 arg z = %.10f rad = %.4f°" % (cmath.phase(z), math.degrees(cmath.phase(z))))
print(" 指数式 z = %.10f · e^(i%.4f°)" % (abs(z), math.degrees(cmath.phase(z))))
print(" ★ 45°、模 √2 —— 这就是「正方形对角线」的复数写法")
print()
print("=== ② 乘法的几何意义:模相乘、角相加 ===")
print(" " + pad("表达式", 20) + pad("结果", 30) + "模 / 辐角")
for label, val in (("z", z), ("z·i(转 90°)", z * complex(0, 1)),
("z·i²(转 180°)", z * complex(0, 1) ** 2),
("z·i⁴(转 360°)", z * complex(0, 1) ** 4),
("z·z̄(共轭乘积)", z * z.conjugate())):
print(" " + pad(label, 20) + pad(fmt(val), 30)
+ "%.6f / %.2f°" % (abs(val), math.degrees(cmath.phase(val)) if abs(val) > 1e-12 else 0.0))
print(" ★ 乘 i 只改角度不改模;乘共轭得到纯实数 |z|² = 2.000000")
print()
print("=== ③ 乘方:(1+i)^n 的模与角都按规则变 ===")
print(" " + pad("n", 6) + pad("(1+i)^n", 26) + pad("模", 16) + pad("辐角(度)", 14) + "理论值")
for n in (1, 2, 3, 4, 8):
v = z ** n
th = math.degrees(cmath.phase(v)) % 360
print(" " + pad(str(n), 6) + pad(fmt(v), 26) + pad("%.6f" % abs(v), 16)
+ pad("%.4f" % th, 14) + "(√2)^%d = %.4f,%d×45° = %d°" % (n, math.sqrt(2) ** n, n, n * 45))
print(" ★ (1+i)^8 = 16:模 (√2)^8 = 16,角 8×45° = 360° ≡ 0° —— 回到正实轴")
print(" ★ 这就是棣莫弗公式 (re^(iθ))^n = r^n e^(inθ) 的直接体现")预期输出:
=== ① 四种表示 ===
代数式 z = 1.0000 + 1.0000i
模 |z| = √(1²+1²) = √2 = 1.4142135624
辐角 arg z = 0.7853981634 rad = 45.0000°
指数式 z = 1.4142135624 · e^(i45.0000°)
★ 45°、模 √2 —— 这就是「正方形对角线」的复数写法
=== ② 乘法的几何意义:模相乘、角相加 ===
表达式 结果 模 / 辐角
z 1.000000 +1.000000i 1.414214 / 45.00°
z·i(转 90°) -1.000000 +1.000000i 1.414214 / 135.00°
z·i²(转 180°) -1.000000 -1.000000i 1.414214 / -135.00°
z·i⁴(转 360°) 1.000000 +1.000000i 1.414214 / 45.00°
z·z̄(共轭乘积) 2.000000 +0.000000i 2.000000 / 0.00°
★ 乘 i 只改角度不改模;乘共轭得到纯实数 |z|² = 2.000000
=== ③ 乘方:(1+i)^n 的模与角都按规则变 ===
n (1+i)^n 模 辐角(度) 理论值
1 1.000000 +1.000000i 1.414214 45.0000 (√2)^1 = 1.4142,1×45° = 45°
2 0.000000 +2.000000i 2.000000 90.0000 (√2)^2 = 2.0000,2×45° = 90°
3 -2.000000 +2.000000i 2.828427 135.0000 (√2)^3 = 2.8284,3×45° = 135°
4 -4.000000 +0.000000i 4.000000 180.0000 (√2)^4 = 4.0000,4×45° = 180°
8 16.000000 +0.000000i 16.000000 0.0000 (√2)^8 = 16.0000,8×45° = 360°
★ (1+i)^8 = 16:模 (√2)^8 = 16,角 8×45° = 360° ≡ 0° —— 回到正实轴
★ 这就是棣莫弗公式 (re^(iθ))^n = r^n e^(inθ) 的直接体现例 2:欧拉公式——把泰勒级数真跑一遍
python
import cmath, math, unicodedata
def w(s):
return sum(2 if unicodedata.east_asian_width(c) in "WF" else 1 for c in s)
def pad(s, n):
return s + " " * max(0, n - w(s))
def expi_partial(theta, n):
"""e^(iθ) 的前 n+1 项部分和:Σ (iθ)^k / k!"""
s, term = 0j, 1 + 0j
for k in range(n + 1):
s += term
term *= (1j * theta) / (k + 1)
return s
print("=== ① 部分和逼近 e^(iθ) ===")
print(" " + pad("θ", 14) + pad("项数", 6) + pad("部分和", 32) + pad("与 e^(iθ) 的误差", 18) + "|部分和|")
for theta, label in ((math.pi / 4, "π/4"), (math.pi, "π"), (2 * math.pi, "2π")):
for n in (2, 5, 10, 20):
v = expi_partial(theta, n)
exact = cmath.exp(1j * theta)
print(" " + pad(label + " = %.4f" % theta, 14) + pad(str(n), 6)
+ pad("%.10f %+.10fi" % (v.real, v.imag), 32)
+ pad("%.3e" % abs(v - exact), 18) + "%.10f" % abs(v))
print()
print(" ★ θ = π 时收敛到 −1 + 0i —— 这就是欧拉恒等式 e^(iπ) = −1")
print(" ★ 任何 θ 下 |e^(iθ)| 恒为 1(在复平面上就是单位圆)")
print()
print("=== ② 三角函数的指数形式(逆用欧拉公式) ===")
print(" cos θ = (e^(iθ) + e^(−iθ))/2,sin θ = (e^(iθ) − e^(−iθ))/(2i)")
print(" " + pad("θ", 10) + pad("cos θ", 18) + pad("指数式算的 cos", 18) + pad("sin θ", 18) + "指数式算的 sin")
for theta in (0.0, math.pi / 6, math.pi / 4, math.pi / 3, math.pi / 2):
c1 = (cmath.exp(1j * theta) + cmath.exp(-1j * theta)) / 2
s1 = (cmath.exp(1j * theta) - cmath.exp(-1j * theta)) / (2j)
print(" " + pad("%.4f" % theta, 10) + pad("%.10f" % math.cos(theta), 18)
+ pad("%.10f" % c1.real, 18) + pad("%.10f" % math.sin(theta), 18)
+ "%.10f" % s1.real)
print(" ★ 两条式子算出的结果逐位相同(虚部为 0,误差在 1e-16 量级)")
print(" ★ 这条「正弦 = 两个指数的差」正是「LTI 系统对正弦只改幅度和相位」的根源")预期输出:
=== ① 部分和逼近 e^(iθ) ===
θ 项数 部分和 与 e^(iθ) 的误差 |部分和|
π/4 = 0.7854 2 0.6915748625 +0.7853981634i 7.982e-02 1.0464827115
π/4 = 0.7854 5 0.7074292067 +0.7071430458i 3.245e-04 1.0002536527
π/4 = 0.7854 10 0.7071067811 +0.7071067829i 1.754e-09 1.0000000012
π/4 = 0.7854 20 0.7071067812 +0.7071067812i 1.570e-16 1.0000000000
π = 3.1416 2 -3.9348022005 +3.1415926536i 4.299e+00 5.0351040464
π = 3.1416 5 0.1239099259 +0.5240439134i 1.240e+00 0.5384939117
π = 3.1416 10 -1.0018291040 +0.0069252707i 7.163e-03 1.0018530396
π = 3.1416 20 -0.9999999999 -0.0000000005i 5.343e-10 0.9999999999
2π = 6.2832 2 -18.7392088022 +6.2831853072i 2.072e+01 19.7645228664
2π = 6.2832 5 46.2001852205 +46.5467323429i 6.488e+01 65.5824321462
2π = 6.2832 10 -5.4382473977 +11.8995665347i 1.353e+01 13.0833565446
2π = 6.2832 20 1.0003012240 -0.0010481828i 1.091e-03 1.0003017732
★ θ = π 时收敛到 −1 + 0i —— 这就是欧拉恒等式 e^(iπ) = −1
★ 任何 θ 下 |e^(iθ)| 恒为 1(在复平面上就是单位圆)
=== ② 三角函数的指数形式(逆用欧拉公式) ===
cos θ = (e^(iθ) + e^(−iθ))/2,sin θ = (e^(iθ) − e^(−iθ))/(2i)
θ cos θ 指数式算的 cos sin θ 指数式算的 sin
0.0000 1.0000000000 1.0000000000 0.0000000000 0.0000000000
0.5236 0.8660254038 0.8660254038 0.5000000000 0.5000000000
0.7854 0.7071067812 0.7071067812 0.7071067812 0.7071067812
1.0472 0.5000000000 0.5000000000 0.8660254038 0.8660254038
1.5708 0.0000000000 0.0000000000 1.0000000000 1.0000000000
★ 两条式子算出的结果逐位相同(虚部为 0,误差在 1e-16 量级)
★ 这条「正弦 = 两个指数的差」正是「LTI 系统对正弦只改幅度和相位」的根源例 3:傅里叶——方波的频谱与"卷积定理"
python
import cmath, math, unicodedata
def w(s):
return sum(2 if unicodedata.east_asian_width(c) in "WF" else 1 for c in s)
def pad(s, n):
return s + " " * max(0, n - w(s))
def dft(x):
N = len(x)
return [sum(x[n] * cmath.exp(-2j * math.pi * k * n / N) for n in range(N)) for k in range(N)]
def idft(X):
N = len(X)
return [sum(X[k] * cmath.exp(2j * math.pi * k * n / N) for k in range(N)) / N for n in range(N)]
def conv_direct(x, h):
N, M = len(x), len(h)
y = [0j] * (N + M - 1)
for n in range(N):
for m in range(M):
y[n + m] += x[n] * h[m]
return y
def b_n(x, n):
"""第 n 次谐波的正弦分量幅度:2/N · Σ x[m]·sin(2πnm/N)"""
N = len(x)
return (2.0 / N) * sum(x[m] * math.sin(2 * math.pi * n * m / N) for m in range(N))
def square(N):
"""奇对称方波:在 0 与 N/2 处取 0,让相位参考对齐(此时 DFT 只有虚部)"""
return [0.0 if m in (0, N // 2) else (1.0 if m < N // 2 else -1.0) for m in range(N)]
def r10(v):
return 0.0 if abs(v) < 1e-12 else v
print("=== ① 方波的傅里叶级数系数:4/(nπ)(n 为奇数) ===")
print(" " + pad("谐波 n", 8) + pad("理论 4/(nπ)", 16) + pad("N=64 实算", 16) + pad("相对误差", 14)
+ pad("N=1024 实算", 16) + "相对误差")
for n in (1, 3, 5, 7, 9):
th = 4 / (n * math.pi)
g64, g1k = b_n(square(64), n), b_n(square(1024), n)
print(" " + pad(str(n), 8) + pad("%.10f" % th, 16) + pad("%.10f" % g64, 16)
+ pad("%.3e" % (abs(g64 - th) / th), 14) + pad("%.10f" % g1k, 16)
+ "%.3e" % (abs(g1k - th) / th))
print(" ★ 幅度按 1/n 衰减:高频分量越来越小,所以方波「听起来」仍有毛刺感")
print(" ★ 采样点越多越接近理论值(N 从 64 到 1024,相对误差降约两个数量级)——")
print(" 这是「用离散采样逼近不连续波形」固有的栅栏误差,与 math/20-numeric.md 是同一件事")
print(" ★ 若只保留前 n 项叠加,会看到吉布斯现象(端点处约 9% 的过冲)")
print()
print("=== ② 卷积定理:时域卷积 = 频域相乘 ===")
x = [1, 2, 3, 4, 0, 0, 0, 0]
h = [1, -0.5, 0.25, 0, 0, 0, 0, 0]
y_direct = conv_direct(x, h)
L = 16 # 必须 >= len(x) + len(h) - 1 = 15,否则循环卷积会「绕回」造成混叠
xz = x + [0.0] * (L - len(x))
hz = h + [0.0] * (L - len(h))
Xf, Hf = dft(xz), dft(hz)
y_via = idft([Xf[k] * Hf[k] for k in range(L)])
y_pad = y_direct + [0j] * (L - len(y_direct))
print(" 输入 x =", x)
print(" 冲激响应 h =", h)
print(" DFT 长度 L = %d(≥ %d + %d − 1 = %d,补零避免循环卷积混叠)"
% (L, len(x), len(h), len(x) + len(h) - 1))
print(" " + pad("n", 6) + pad("直接卷积", 22) + pad("频域相乘再逆变换", 22) + "差值")
for n in range(L):
print(" " + pad(str(n), 6) + pad("%.10f" % r10(y_pad[n].real), 22)
+ pad("%.10f" % r10(y_via[n].real), 22) + "%.3e" % abs(y_pad[n] - y_via[n]))
print(" ★ 两条路结果逐位一致(差值都在 1e-14 以内)—— 这就是「滤波器 = 频域乘一个形状」")
print(" ★ 计算量:直接卷积 O(n²);用 FFT 走频域是 O(n log n) —— 大 n 时快几个数量级")预期输出:
=== ① 方波的傅里叶级数系数:4/(nπ)(n 为奇数) ===
谐波 n 理论 4/(nπ) N=64 实算 相对误差 N=1024 实算 相对误差
1 1.2732395447 1.2722167266 8.033e-04 1.2732355500 3.137e-06
3 0.4244131816 0.4213407753 7.239e-03 0.4244011973 2.824e-05
5 0.2546479089 0.2495139865 2.016e-02 0.2546279349 7.844e-05
7 0.1818913635 0.1746757983 3.967e-02 0.1818633995 1.537e-04
9 0.1414710605 0.1321451473 6.592e-02 0.1414351060 2.541e-04
★ 幅度按 1/n 衰减:高频分量越来越小,所以方波「听起来」仍有毛刺感
★ 采样点越多越接近理论值(N 从 64 到 1024,相对误差降约两个数量级)——
这是「用离散采样逼近不连续波形」固有的栅栏误差,与 math/20-numeric.md 是同一件事
★ 若只保留前 n 项叠加,会看到吉布斯现象(端点处约 9% 的过冲)
=== ② 卷积定理:时域卷积 = 频域相乘 ===
输入 x = [1, 2, 3, 4, 0, 0, 0, 0]
冲激响应 h = [1, -0.5, 0.25, 0, 0, 0, 0, 0]
DFT 长度 L = 16(≥ 8 + 8 − 1 = 15,补零避免循环卷积混叠)
n 直接卷积 频域相乘再逆变换 差值
0 1.0000000000 1.0000000000 1.078e-15
1 1.5000000000 1.5000000000 1.665e-16
2 2.2500000000 2.2500000000 1.340e-15
3 3.0000000000 3.0000000000 2.220e-16
4 -1.2500000000 -1.2500000000 6.280e-16
5 1.0000000000 1.0000000000 1.201e-15
6 0.0000000000 0.0000000000 2.804e-15
7 0.0000000000 0.0000000000 3.271e-15
8 0.0000000000 0.0000000000 2.162e-15
9 0.0000000000 0.0000000000 1.410e-15
10 0.0000000000 0.0000000000 1.977e-15
11 0.0000000000 0.0000000000 1.988e-15
12 0.0000000000 0.0000000000 5.818e-15
13 0.0000000000 0.0000000000 1.990e-15
14 0.0000000000 0.0000000000 5.950e-15
15 0.0000000000 0.0000000000 3.973e-15
★ 两条路结果逐位一致(差值都在 1e-14 以内)—— 这就是「滤波器 = 频域乘一个形状」
★ 计算量:直接卷积 O(n²);用 FFT 走频域是 O(n log n) —— 大 n 时快几个数量级例 4:拉普拉斯变换解 RC 电路(与 math/10 对照)
python
import math, unicodedata
def w(s):
return sum(2 if unicodedata.east_asian_width(c) in "WF" else 1 for c in s)
def pad(s, n):
return s + " " * max(0, n - w(s))
RC, VS = 1.0, 5.0
print("=== ① 时域 → s 域 → 时域 ===")
print(" 1) 时域方程:RC·dv/dt + v = VS,v(0) = 0")
print(" 2) 拉普拉斯(用 f' ↔ sF(s) − f(0)):RC·[sV(s) − 0] + V(s) = VS/s")
print(" 3) 代数整理:V(s)(1 + sRC) = VS/s ⇒ V(s) = VS / [s(1 + sRC)]")
print(" 4) 部分分式:V(s) = VS·[1/s − 1/(s + 1/RC)]")
print(" 5) 逆变换(查表:1/s ↔ 1,1/(s+a) ↔ e^(−at))")
print(" v(t) = VS·(1 − e^(−t/RC))")
print()
print(" 数值核对(RC = %.1f,VS = %.1f):解析解 vs 直接对 ODE 做欧拉法积分(dt = RC/1000)" % (RC, VS))
print(" " + pad("t", 8) + pad("拉普拉斯解析解", 20) + pad("欧拉法数值解", 20) + "相对误差")
def euler(t_end, dt):
"""直接对 dv/dt = (VS − v)/RC 做前向欧拉,检验解析解确实是它的解"""
v, n = 0.0, int(round(t_end / dt))
for _ in range(n):
v += dt * (VS - v) / RC
return v
for k in (0, 1, 2, 3, 5):
t = k * RC
a = VS * (1 - math.exp(-t / RC))
b = euler(t, RC / 1000.0)
print(" " + pad("%d·RC" % k, 8) + pad("%.12f" % a, 20) + pad("%.12f" % b, 20)
+ "%.3e" % (abs(a - b) / a if a > 0 else 0.0))
print(" ★ 两条路一致:拉普拉斯解出的 v(t) 确实是那条 ODE 的解(欧拉法误差在 1e-4 量级以内,随 dt 减小)")
print()
print(" t50 = RC·ln2 = %.6f·RC,与 circuit/02-rc.md 的 0.6931τ 完全一致" % math.log(2))
print()
print("=== ② 极点在哪儿:从 H(s) 一眼看出行为 ===")
print(" 系统函数 H(s) = V(s)/[VS/s] = 1/(1 + sRC)")
print(" 极点:1 + sRC = 0 ⇒ s = −1/RC = %.4f" % (-1 / RC))
print(" ★ 极点在负实轴上(左半平面)→ 指数衰减 → 稳定")
print(" ★ 时间常数 τ = RC = 1/|极点| = %.4f,与电路里的 τ 是同一个数" % (1 / abs(-1 / RC)))预期输出:
=== ① 时域 → s 域 → 时域 ===
1) 时域方程:RC·dv/dt + v = VS,v(0) = 0
2) 拉普拉斯(用 f' ↔ sF(s) − f(0)):RC·[sV(s) − 0] + V(s) = VS/s
3) 代数整理:V(s)(1 + sRC) = VS/s ⇒ V(s) = VS / [s(1 + sRC)]
4) 部分分式:V(s) = VS·[1/s − 1/(s + 1/RC)]
5) 逆变换(查表:1/s ↔ 1,1/(s+a) ↔ e^(−at))
v(t) = VS·(1 − e^(−t/RC))
数值核对(RC = 1.0,VS = 5.0):解析解 vs 直接对 ODE 做欧拉法积分(dt = RC/1000)
t 拉普拉斯解析解 欧拉法数值解 相对误差
0·RC 0.000000000000 0.000000000000 0.000e+00
1·RC 3.160602794143 3.161522876145 2.911e-04
2·RC 4.323323583817 4.324000373012 1.565e-04
3·RC 4.751064658161 4.751438030010 7.859e-05
5·RC 4.966310265005 4.966394440201 1.695e-05
★ 两条路一致:拉普拉斯解出的 v(t) 确实是那条 ODE 的解(欧拉法误差在 1e-4 量级以内,随 dt 减小)
t50 = RC·ln2 = 0.693147·RC,与 circuit/02-rc.md 的 0.6931τ 完全一致
=== ② 极点在哪儿:从 H(s) 一眼看出行为 ===
系统函数 H(s) = V(s)/[VS/s] = 1/(1 + sRC)
极点:1 + sRC = 0 ⇒ s = −1/RC = -1.0000
★ 极点在负实轴上(左半平面)→ 指数衰减 → 稳定
★ 时间常数 τ = RC = 1/|极点| = 1.0000,与电路里的 τ 是同一个数例 5:极点位置决定稳定性(连续与离散对照)
python
import cmath, math, unicodedata
def w(s):
return sum(2 if unicodedata.east_asian_width(c) in "WF" else 1 for c in s)
def pad(s, n):
return s + " " * max(0, n - w(s))
def roots2(a, b, c):
d = cmath.sqrt(b * b - 4 * a * c)
return [(-b + d) / (2 * a), (-b - d) / (2 * a)]
def stable_cont(rs):
return all(r.real < 0 for r in rs)
def stable_disc(rs):
return all(abs(r) < 1 for r in rs)
print("=== ① 连续系统:极点必须落在左半平面(Re s < 0) ===")
print(" " + pad("分母 D(s)", 20) + pad("极点", 34) + pad("稳定", 8) + "时域行为")
CASES = [
("s² + 3s + 2", 1, 3, 2),
("s² + 2s + 1", 1, 2, 1),
("s² + 2s + 5", 1, 2, 5),
("s² − 1", 1, 0, -1),
("s² + 1", 1, 0, 1),
]
for name, a, b, c in CASES:
rs = roots2(a, b, c)
ok = stable_cont(rs)
if all(abs(r.imag) < 1e-12 for r in rs):
form = "两个实根 → 指数(无振荡)"
else:
re0 = rs[0].real
form = "共轭复根 → " + ("衰减振荡" if re0 < 0 else ("等幅振荡" if abs(re0) < 1e-12 else "发散振荡"))
print(" " + pad(name, 20) + pad(" ".join(fmt_ := "%.4f%+.4fi" % (r.real, r.imag) for r in rs), 34)
+ pad("是" if ok else "否", 8) + form)
print(" ★ s² − 1 的极点在 ±1(有一个正实部)→ 指数发散;s² + 1 的极点在 ±i(实部为 0)→ 等幅振荡")
print(" ★ 判据:全部极点 Re < 0 ⟺ 稳定;这与 auto 里「极点在左半平面」是同一句话")
print()
print("=== ② 离散系统:极点必须落在单位圆内(|z| < 1) ===")
print(" " + pad("H(z)", 22) + pad("极点 z", 14) + pad("|z|", 12) + pad("稳定", 8) + "冲激响应 h[n]")
DISC = [
("1/(1 − 0.5z⁻¹)", [0.5]),
("1/(1 − 0.9z⁻¹)", [0.9]),
("1/(1 − 1.0z⁻¹)", [1.0]),
("1/(1 − 1.2z⁻¹)", [1.2]),
("1/(1 + 0.5z⁻¹)", [-0.5]),
]
for name, rs in DISC:
ok = stable_disc(rs)
z = rs[0]
if abs(z) < 1:
trend = "h[n] = %.2f^n → 衰减到 0" % z
elif abs(z) == 1:
trend = "h[n] ≡ 1 → 不衰减(临界)"
else:
trend = "h[n] = %.2f^n → 发散" % z
print(" " + pad(name, 22) + pad("%.4f" % z, 14) + pad("%.4f" % abs(z), 12)
+ pad("是" if ok else "否", 8) + trend)
print(" ★ 极点在圆内 → 衰减;圆上 → 临界;圆外 → 发散")
print(" ★ 对应关系:连续 s 平面左半平面 ↔ 离散 z 平面单位圆内(z = e^(sT))")
print()
print("=== ③ 冲激响应实算两例(把「衰减 / 发散」跑出来) ===")
for z in (0.5, 1.2):
seq = [z ** n for n in range(8)]
print(" z = %.1f:" % z + " ".join("%.5f" % v for v in seq))
print(" ★ z = 0.5 快速衰减(稳定);z = 1.2 迅速发散(不稳定)—— 极点的模就是衰减率")预期输出:
=== ① 连续系统:极点必须落在左半平面(Re s < 0) ===
分母 D(s) 极点 稳定 时域行为
s² + 3s + 2 -1.0000+0.0000i -2.0000+0.0000i 是 两个实根 → 指数(无振荡)
s² + 2s + 1 -1.0000+0.0000i -1.0000+0.0000i 是 两个实根 → 指数(无振荡)
s² + 2s + 5 -1.0000+2.0000i -1.0000-2.0000i 是 共轭复根 → 衰减振荡
s² − 1 1.0000+0.0000i -1.0000+0.0000i 否 两个实根 → 指数(无振荡)
s² + 1 0.0000+1.0000i 0.0000-1.0000i 否 共轭复根 → 等幅振荡
★ s² − 1 的极点在 ±1(有一个正实部)→ 指数发散;s² + 1 的极点在 ±i(实部为 0)→ 等幅振荡
★ 判据:全部极点 Re < 0 ⟺ 稳定;这与 auto 里「极点在左半平面」是同一句话
=== ② 离散系统:极点必须落在单位圆内(|z| < 1) ===
H(z) 极点 z |z| 稳定 冲激响应 h[n]
1/(1 − 0.5z⁻¹) 0.5000 0.5000 是 h[n] = 0.50^n → 衰减到 0
1/(1 − 0.9z⁻¹) 0.9000 0.9000 是 h[n] = 0.90^n → 衰减到 0
1/(1 − 1.0z⁻¹) 1.0000 1.0000 否 h[n] ≡ 1 → 不衰减(临界)
1/(1 − 1.2z⁻¹) 1.2000 1.2000 否 h[n] = 1.20^n → 发散
1/(1 + 0.5z⁻¹) -0.5000 0.5000 是 h[n] = -0.50^n → 衰减到 0
★ 极点在圆内 → 衰减;圆上 → 临界;圆外 → 发散
★ 对应关系:连续 s 平面左半平面 ↔ 离散 z 平面单位圆内(z = e^(sT))
=== ③ 冲激响应实算两例(把「衰减 / 发散」跑出来) ===
z = 0.5:1.00000 0.50000 0.25000 0.12500 0.06250 0.03125 0.01562 0.00781
z = 1.2:1.00000 1.20000 1.44000 1.72800 2.07360 2.48832 2.98598 3.58318
★ z = 0.5 快速衰减(稳定);z = 1.2 迅速发散(不稳定)—— 极点的模就是衰减率考点
考点
1. 复数的四种表示与一条几何直觉
- 代数
a+bi、几何(复平面上的点)、三角r(cosθ+isinθ)、指数re^{iθ}; |z| = √(a²+b²),θ = arg z;乘除用指数式最省事;- ★ 乘法 = 模相乘、角相加(所以"乘
i就是转 90°"); z·z̄ = |z|²;棣莫弗(re^{iθ})^n = r^n e^{inθ};- 锚点:
(1+i)^8 = 16(模(√2)^8 = 16,角8×45° = 360° ≡ 0°)。
2. 欧拉公式与两个推论
- 来历:把
e^{iθ}的泰勒级数按i² = −1两两合并; |e^{iθ}| ≡ 1(单位圆);e^{iπ} = −1;- "三角函数是指数的线性组合"——这是"LTI 系统对正弦只改幅度和相位"的根源。
3. 复变函数的三条关键结论
- 解析条件:柯西-黎曼方程
u_x = v_y、u_y = −v_x; - 解析 ⇒ 无穷次可导;实部虚部都是调和函数(
∇²u = 0); - 极点:
H(s) = N(s)/D(s)中D(s) = 0的根;留数定理∮ = 2πi·ΣRes。
4. 傅里叶变换:四个变换对 + 四条性质
| 时域 | 频域 |
|---|---|
δ(t) | 1 |
1 | 2πδ(ω) |
e^{−at}u(t) | 1/(a+iω) |
宽 T 的矩形脉冲 | T·sinc(ωT/2) |
- 线性;时移 → 乘
e^{−iωt₀}(只改相位不改幅度); - ★ 卷积 → 相乘("滤波器 = 频域乘一个形状";FFT 把
O(n²)降到O(n log n)); - 帕塞瓦尔:
∫|f|²dt = (1/2π)∫|F|²dω(能量守恒); - 采样定理:
f_s > 2f_max(回链elec/13-sampling.md)。
5. 拉普拉斯变换:三条钥匙性质
- 微分:
f'(t) ↔ sF(s) − f(0⁻)("微分变乘法"——整个方法的核心); - 积分:
∫f ↔ F(s)/s;卷积:f*g ↔ F(s)G(s); - 初值/终值定理:
f(0⁺) = lim_{s→∞} sF(s),f(∞) = lim_{s→0} sF(s); - 解 RC 电路五步:
RC·v' + v = V_S→V(s) = V_S/[s(1+sRC)]→ 部分分式 →v(t) = V_S(1 − e^{−t/RC}); - 比傅里叶多一个实部
σ,换来"更多信号可变换",代价是要管收敛域。
6. Z 变换(离散版)
X(z) = Σ x[n]z^{−n};z = e^{sT};z^{−1}= 延迟一拍(硬件里就是一个寄存器);- 连续左半平面 ↔ 离散单位圆内;
- 数字滤波器
H(z) = Y(z)/X(z)。
7. 稳定性:一句话贯穿全篇
8. 本节五个易错点
arg z是多值的(差2π的整数倍)——"转 360° 回到原处"正是这个意思;e^{iθ}的模恒为 1,别把它当成随 θ 增长的量;- 拉普拉斯 ≠ 傅里叶:多了实部
σ、必须写收敛域; - "极点在虚轴上"是临界(等幅振荡),不算稳定(离散里对应"极点在单位圆上");
- 卷积定理是"时域卷积 ↔ 频域相乘",不是相反——时域相乘对应频域卷积。
小结
- 复数 = 缩放 + 旋转:
re^{iθ};乘法 = 模相乘、角相加;(1+i)^8 = 16。 - 欧拉公式
e^{iθ} = cosθ + isinθ:由泰勒级数两两合并而来;|e^{iθ}| ≡ 1;三角函数是它的线性组合。 - 复变函数:解析要满足柯西-黎曼方程;解析则无穷次可导、实虚部调和;极点 = 分母的根。
- 傅里叶变换:时域 ↔ 频域;四个变换对(冲激↔1、直流↔
2πδ、指数衰减↔1/(a+iω)、矩形↔sinc);卷积 → 相乘;帕塞瓦尔管能量;采样定理管混叠。 - 拉普拉斯变换:"微分变乘
s",于是微分方程变代数方程;解 RC 得到v = V_S(1 − e^{−t/RC}),与math/10的分离变量法结果完全一致。 - Z 变换:离散版;
z^{−1}是延迟一拍;极点看单位圆。 - 一条主线串到底:极点/特征根的位置决定行为——连续看左半平面、离散看单位圆内。
回到主线:这是 math 的最后一篇,也是对整门课的收线。
它把前三篇散落的"同一件事"收成了一句:
math/10-calculus.md里"二阶微分方程看特征根实部定稳定性"math/11-linalg.md里"状态矩阵的特征值实部为负则稳定"math/20-numeric.md里"迭代收敛看谱半径ρ < 1"本篇里"极点落在左半平面(连续)/ 单位圆内(离散)"——这是同一句话在四套语言里的四种说法。而
math这门课自身的定位也在这里收口:它不做独立体系,按主线需要取用—— ·math/01-discrete.md→ L1 数字电路(硬前置);·math/10-calculus.md→circuit的τ ln2、arch的浮点与性能极限;·math/11-linalg.md→soft图形学与机器学习、auto的状态方程;·math/12-probability.md→arch的命中率、ds的 ASL、os的排队;·math/20-numeric.md→arch的浮点误差、一切数值方法的可信度;·math/21-complex.md→elec信号与系统的直接前置。
下一篇离开 math,进入 elec(分支 · 电子与通信):信号与系统、傅里叶与拉普拉斯、DSP、通信原理。 本篇的复数、极点、卷积定理会在那里被当成"日常工具"反复使用——因为它们本来就长在那里。
评论(0)
当前浏览器不允许本地存储,评论无法保存。
还没有评论,来说两句。