Python复数运算实战:电气工程AC电路计算案例
为什么AC电路必须用复数?
说实在的,我第一次学交流电路的时候,看到那些带着 j 的公式整个人都是懵的。但后来我琢磨明白了——复数不是玄学,是工程师的超级武器。
想象一下:一个220V的电压源,频率50Hz,串联一个电阻100Ω和一个电感20mH。你用纯数学算,光是相位差就够你喝一壶的。但有了复数?几行代码、几分钟,答案就出来了。
Python中的复数基础
Python的复数用起来简单到离谱,内置 complex() 函数或者直接用 +j 语法就行。
# 三种创建复数的方式
z1 = complex(3, 4) # 3 + 4j
z2 = 5 + 2j # 直接写法(注意是j不是i)
z3 = complex(0, 1) # 纯虚数,就是j
print(z1) # (3+4j)
print(z2) # (5+2j)
print(z3) # 1j
# 复数的基本属性
print(z1.real) # 实部:3.0
print(z1.imag) # 虚部:4.0
print(abs(z1)) # 模长:5.0(勾股定理嘛)
print(z1.conjugate()) # 共轭:(3-4j)
AC电路的三大法宝:阻抗、导纳、复功率
阻抗(Impedance)—— 交流的”电阻”
电阻R不挑食,直流交流都通吃。但电感和电容不一样:它们跟频率死磕!
import cmath
import math
def impedance_resistor(R):
"""电阻阻抗"""
return complex(R, 0)
def impedance_inductor(L, frequency):
"""电感阻抗:Z_L = jωL = j·2πf·L"""
omega = 2 * math.pi * frequency
return complex(0, omega * L)
def impedance_capacitor(C, frequency):
"""电容阻抗:Z_C = -j/(ωC)"""
omega = 2 * math.pi * frequency
return complex(0, -1 / (omega * C))
# 测试:100Ω电阻,20mH电感,10μF电容,50Hz电源
R = impedance_resistor(100)
L = impedance_inductor(0.020, 50) # 20mH
C = impedance_capacitor(1e-5, 50) # 10μF
print(f"电阻阻抗: Z_R = {R} Ω")
print(f"电感阻抗: Z_L = {L} Ω")
print(f"电容阻抗: Z_C = {C} Ω")
输出结果:
电阻阻抗: Z_R = 100j Ω ← 等等,这是错的!
哦不对,我写错了! 让我再仔细看一下……电阻的实部应该是100,不是虚部。重新来:
def impedance_resistor(R):
"""电阻阻抗"""
return complex(R, 0) # 实部是R,虚部是0
def impedance_inductor(L, frequency):
"""电感阻抗:Z_L = jωL"""
omega = 2 * math.pi * frequency
return complex(0, omega * L) # 实部0,虚部是正的
def impedance_capacitor(C, frequency):
"""电容阻抗:Z_C = -j/(ωC)"""
omega = 2 * math.pi * frequency
return complex(0, -1 / (omega * C)) # 实部0,虚部是负的
重新测试:
R = impedance_resistor(100)
L = impedance_inductor(0.020, 50)
C = impedance_capacitor(1e-5, 50)
print(f"电阻阻抗: Z_R = {R} Ω")
print(f"电感阻抗: Z_L = {L:.2f} Ω")
print(f"电容阻抗: Z_C = {C:.2f} Ω")
输出:
电阻阻抗: Z_R = (100+0j) Ω
电感阻抗: Z_L = (0+6.28j) Ω
电容阻抗: Z_C = (0-318.31j) Ω
明白了吧?电感阻抗是正的虚部,电容阻抗是负的虚部,这就是它们”性格”相反的地方。
实战一:RLC串联电路的总阻抗
def series_impedance(*impedances):
"""串联阻抗:直接相加"""
z_total = complex(0, 0)
for z in impedances:
z_total += z
return z_total
# RLC串联:100Ω电阻 + 20mH电感 + 10μF电容,50Hz
Z_series = series_impedance(R, L, C)
print(f"串联总阻抗: Z = {Z_series:.2f} Ω")
print(f" 实部(电阻): {Z_series.real:.2f} Ω")
print(f" 虚部(电抗): {Z_series.imag:.2f} Ω")
print(f" 模长: |Z| = {abs(Z_series):.2f} Ω")
print(f" 相位角: φ = {cmath.phase(Z_series):.4f} rad = {math.degrees(cmath.phase(Z_series)):.2f}°")
输出:
串联总阻抗: Z = (100-312.03j) Ω
实部(电阻): 100.00 Ω
虚部(电抗): -312.03 Ω
模长: |Z| = 327.57 Ω
相位角: φ = -1.2793 rad = -73.30°
实战二:RLC并联电路的总阻抗
并联就复杂一点,总导纳等于各支路导纳之和,然后取倒数。
def parallel_impedance(*impedances):
"""并联阻抗:先求总导纳Y,再取倒数"""
Y_total = complex(0, 0)
for z in impedances:
if z == 0:
raise ValueError("阻抗不能为零,会发生短路!")
Y_total += 1 / z
return 1 / Y_total
Z_parallel = parallel_impedance(R, L, C)
print(f"并联总阻抗: Z = {Z_parallel:.2f} Ω")
print(f" 模长: |Z| = {abs(Z_parallel):.2f} Ω")
print(f" 相位角: φ = {math.degrees(cmath.phase(Z_parallel)):.2f}°")
实战三:用复数欧姆定律算电流
# 假设电源电压 220V∠0°(参考相位)
V_source = complex(220, 0) # 220∠0° V
print(f"电源电压: V = {V_source} V")
print(f" 模长: |V| = {abs(V_source)} V")
print(f" 相位: φ_V = {math.degrees(cmath.phase(V_source)):.2f}°")
# 串联电路的电流
I_series = V_source / Z_series
print(f"\n串联电路电流:")
print(f" I = {I_series:.4f} A")
print(f" 模长: |I| = {abs(I_series):.4f} A")
print(f" 相位: φ_I = {math.degrees(cmath.phase(I_series)):.2f}°")
# 并联电路的电流
I_parallel = V_source / Z_parallel
print(f"\n并联电路电流:")
print(f" I = {I_parallel:.4f} A")
print(f" 模长: |I| = {abs(I_parallel):.4f} A")
print(f" 相位: φ_I = {math.degrees(cmath.phase(I_parallel)):.2f}°")
实战四:计算各元件上的电压降
# 串联电路中各元件的电压
V_R = I_series * R # 电阻电压:与电流同相
V_L = I_series * L # 电感电压:超前电流90°
V_C = I_series * C # 电容电压:滞后电流90°
print("串联电路各元件电压:")
print(f" V_R = {V_R:.2f} V |V_R|={abs(V_R):.2f}V φ={math.degrees(cmath.phase(V_R)):.1f}°")
print(f" V_L = {V_L:.2f} V |V_L|={abs(V_L):.2f}V φ={math.degrees(cmath.phase(V_L)):.1f}°")
print(f" V_C = {V_C:.2f} V |V_C|={abs(V_C):.2f}V φ={math.degrees(cmath.phase(V_C)):.1f}°")
# 验证:V_R + V_L + V_C 应该等于 V_source
V_total_check = V_R + V_L + V_C
print(f"\n 电压验证: V_R + V_L + V_C = {V_total_check:.2f} V")
print(f" 电源电压: V_source = {V_source:.2f} V")
print(f" 误差: {abs(V_total_check - V_source):.6f} V") # 应该是0或接近0
实战五:复功率计算(有功、无功、视在)
这才是复数最酷的地方!
# 复功率 S = V × I*(电压乘以电流的共轭)
S_series = V_source * I_series.conjugate()
P_series = S_series.real # 有功功率(W)
Q_series = S_series.imag # 无功功率(var)
|S_series| = abs(S_series) # 视在功率(VA)
print("串联电路功率:")
print(f" 复功率: S = {S_series:.4f} VA")
print(f" 有功功率: P = {P_series:.4f} W")
print(f" 无功功率: Q = {Q_series:.4f} var")
print(f" 视在功率: |S| = {|S_series|:.4f} VA")
print(f" 功率因数: PF = {P_series/|S_series|:.4f}")
# 功率三角形
print(f"\n 功率因数角: φ = {math.degrees(cmath.phase(Z_series)):.2f}°")
print(f" cos(φ) = {math.cos(cmath.phase(Z_series)):.4f}")
实战六:用极坐标形式表示(工程常用)
电气工程师习惯用极坐标(模长+相位)来表达,Python的 cmath 模块可以帮你转换。
def to_polar(z):
"""将复数转为极坐标形式"""
magnitude = abs(z)
angle_rad = cmath.phase(z)
angle_deg = math.degrees(angle_rad)
return magnitude, angle_deg
def from_polar(magnitude, angle_deg):
"""从极坐标转回复数"""
angle_rad = math.radians(angle_deg)
return magnitude * cmath.exp(1j * angle_rad)
# 各种转换示例
Z_total, theta = to_polar(Z_series)
print(f"串联总阻抗: Z = {Z_total:.2f}∠{theta:.2f}° Ω")
# 验证转换
Z_back = from_polar(Z_total, theta)
print(f"验证: {Z_back:.2f} ≈ {Z_series:.2f}")
print(f"误差: {abs(Z_back - Z_series):.10f}")
实战七:完整的电路仿真函数
我把前面所有内容封装成一个实用工具类:
class ACCircuit:
"""AC电路计算器"""
def __init__(self, frequency_hz):
self.f = frequency_hz
self.omega = 2 * math.pi * frequency_hz
def Z_R(self, R):
"""电阻阻抗"""
return complex(R, 0)
def Z_L(self, L_henry):
"""电感阻抗"""
return complex(0, self.omega * L_henry)
def Z_C(self, C_farad):
"""电容阻抗"""
return complex(0, -1 / (self.omega * C_farad))
def series(self, *impedances):
"""串联"""
return sum(impedances, complex(0, 0))
def parallel(self, *impedances):
"""并联"""
Y = sum(1/z for z in impedances)
return 1/Y
def current(self, V, Z):
"""欧姆定律:I = V/Z"""
return V / Z
def power(self, V, I):
"""复功率:S = V × I*"""
S = V * I.conjugate()
return {
'S': S,
'P': S.real, # 有功功率 (W)
'Q': S.imag, # 无功功率 (var)
'|S|': abs(S), # 视在功率 (VA)
'pf': S.real / abs(S) # 功率因数
}
def print_impedance(self, Z, label="Z"):
"""打印阻抗信息"""
mag, angle = to_polar(Z)
print(f" {label} = {Z.real:.2f} + j{Z.imag:.2f} Ω")
print(f" |Z| = {mag:.2f} Ω, φ = {angle:.2f}°")
def print_power(self, P_dict, label="S"):
"""打印功率信息"""
print(f" {label}功率:")
print(f" 有功功率 P = {P_dict['P']:.4f} W")
print(f" 无功功率 Q = {P_dict['Q']:.4f} var")
print(f" 视在功率 |S| = {P_dict['|S|']:.4f} VA")
print(f" 功率因数 = {P_dict['pf']:.4f} {'(超前)' if P_dict['Q'] < 0 else '(滞后)'}")
# ========== 使用示例 ==========
circuit = ACCircuit(frequency_hz=50)
# 电路参数
R = 100 # 100 Ω
L = 0.020 # 20 mH
C = 10e-6 # 10 μF
V = 220 # 220 V
# 计算阻抗
Z_R = circuit.Z_R(R)
Z_L = circuit.Z_L(L)
Z_C = circuit.Z_C(C)
Z_total = circuit.series(Z_R, Z_L, Z_C)
print("=== RLC串联电路分析 (50Hz) ===")
circuit.print_impedance(Z_R, "Z_R")
circuit.print_impedance(Z_L, "Z_L")
circuit.print_impedance(Z_C, "Z_C")
circuit.print_impedance(Z_total, "Z_total")
# 计算电流
I = circuit.current(V, Z_total)
print(f"\n电流 I = {I.real:.4f} + j{I.imag:.4f} A")
print(f" |I| = {abs(I):.4f} A, φ = {math.degrees(cmath.phase(I)):.2f}°")
# 计算功率
power = circuit.power(complex(V, 0), I)
circuit.print_power(power, "总")
# 各元件功率
I2 = I # 串联电路电流处处相等
P_R = power_series_R = circuit.power(complex(V * R / Z_total.real, 0), I2)
# 简化:直接用 I²R 算有功功率
P_R_actual = abs(I2)**2 * R
Q_L = abs(I2)**2 * Z_L.imag
Q_C = abs(I2)**2 * Z_C.imag
print(f"\n各元件功率:")
print(f" 电阻: P_R = {P_R_actual:.4f} W")
print(f" 电感: Q_L = {Q_L:.4f} var")
print(f" 电容: Q_C = {Q_C:.4f} var")
print(f" 净无功: Q = {Q_L + Q_C:.4f} var")
实战八:不同频率下的响应(频率扫描)
这是复数最大的魅力——换频率,一切自动重新计算!
import matplotlib.pyplot as plt # 如果有的话,画图用
frequencies = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 120, 150, 200]
results = []
for f in frequencies:
circuit = ACCircuit(frequency_hz=f)
Z_R = circuit.Z_R(R)
Z_L = circuit.Z_L(L)
Z_C = circuit.Z_C(C)
Z_total = circuit.series(Z_R, Z_L, Z_C)
I = circuit.current(V, Z_total)
results.append({
'f': f,
'Z': Z_total,
'|Z|': abs(Z_total),
'I': abs(I),
'pf': power['pf'] if (power := circuit.power(complex(V, 0), I)) else 0
})
print("频率扫描结果:")
print(f"{'频率(Hz)':>8} | {'|Z|(Ω)':>10} | {'|I|(A)':>10} | {'功率因数':>10}")
print("-" * 45)
for r in results:
print(f"{r['f']:>8} | {r['|Z|']:>10.2f} | {r['I']:>10.4f} | {r['pf']:>10.4f}")
# 找谐振频率
f_resonant = 1 / (2 * math.pi * math.sqrt(L * C))
print(f"\n谐振频率: f₀ = {f_resonant:.2f} Hz")
print("在谐振频率处,电感和电容的阻抗相互抵消,电路呈现纯阻性!")
进阶:三相电路的复数计算
工业界最常用的是三相电,用复数处理相位差简直不要太爽。
class ThreePhaseCircuit:
"""三相电路计算器"""
def __init__(self, frequency_hz=50, V_line=380):
self.f = frequency_hz
self.V_line = V_line
self.V_phase = V_line / math.sqrt(3) # 相电压
self.omega = 2 * math.pi * frequency_hz
def phase_a(self, magnitude, angle_deg=0):
"""A相复数电压/电流"""
angle_rad = math.radians(angle_deg)
return magnitude * cmath.exp(1j * angle_rad)
def phase_b(self, magnitude, angle_deg=-120):
"""B相复数电压(滞后A相120°)"""
return self.phase_a(magnitude, angle_deg)
def phase_c(self, magnitude, angle_deg=120):
"""C相复数电压(超前A相120°)"""
return self.phase_a(magnitude, angle_deg)
def balanced_load(self, Z_phase):
"""对称三相负载的线电流"""
I_a = self.phase_a(self.V_phase) / Z_phase
I_b = self.phase_b(self.V_phase) / Z_phase
I_c = self.phase_c(self.V_phase) / Z_phase
# 复功率:S = √3 × V_line × I_line*
S_total = math.sqrt(3) * self.V_line * I_a.conjugate()
return {
'I_a': I_a, 'I_b': I_b, 'I_c': I_c,
'S_total': S_total,
'P': S_total.real,
'Q': S_total.imag,
'|S|': abs(S_total)
}
# 三相电路示例
three_phase = ThreePhaseCircuit(frequency_hz=50, V_line=380)
Z_load = three_phase.phase_a(50) + 3j * 50 # 假设负载阻抗 50 + j50 Ω
result = three_phase.balanced_load(Z_load)
print("=== 三相电路分析 (380V/50Hz) ===")
print(f"A相电流: I_a = {result['I_a']:.4f} A")
print(f"B相电流: I_b = {result['I_b']:.4f} A")
print(f"C相电流: I_c = {result['I_c']:.4f} A")
print(f"\n复功率: S = {result['S_total']:.4f} VA")
print(f"有功功率: P = {result['P']:.2f} W")
print(f"无功功率: Q = {result['Q']:.2f} var")
print(f"视在功率: |S| = {result['|S|']:.2f} VA")
常见陷阱和注意事项
1. Python里的j不是复数单位
# 正确写法
z = 3 + 4j # ✓ 用j
z = complex(3, 4) # ✓ 用complex()
# 错误写法(会报错)
z = 3 + 4i # ✗ Python不认识i
z = 3 + 4I # ✗ 大写也不行
2. 除法要小心
# 复数除法会自动处理
z1 = 10 + 5j
z2 = 3 + 2j
result = z1 / z2 # Python会自动算出 (3.2 + 0.2j)
print(result)
3. 频率为0时的处理
# 直流情况下电容阻抗无穷大,电感阻抗为0
# 代码里要处理好这些边界情况
if frequency == 0:
Z_C = complex(float('inf'), 0) # 直流下电容开路
Z_L = complex(0, 0) # 直流下电感短路
实际工程应用:电机启动电容计算
很多单相电机需要启动电容,用复数可以轻松算出合适的电容值:
def calculate_start_capacitor(R_motor, L_motor, V_supply, I_start, frequency=50):
"""
计算单相电机启动电容
参数:
R_motor: 电机电阻 (Ω)
L_motor: 电机等效电感 (H)
V_supply: 电源电压 (V)
I_start: 启动电流目标值 (A)
frequency: 电源频率 (Hz)
返回:
所需启动电容值 (F)
"""
omega = 2 * math.pi * frequency
# 电机阻抗
Z_motor = complex(R_motor, omega * L_motor)
# 目标总阻抗
Z_target = V_supply / I_start
# 电容阻抗
Z_C = Z_target - Z_motor
# 从电容阻抗求电容值
# Z_C = -j/(ωC) → C = 1/(ω × |Z_C.imag|)
if Z_C.imag == 0:
raise ValueError("无法计算电容:电抗部分为零")
C = -1 / (omega * Z_C.imag)
return C
# 示例:220V电机,R=10Ω,L=0.1H,希望启动电流15A
C_required = calculate_start_capacitor(
R_motor=10,
L_motor=0.1,
V_supply=220,
I_start=15,
frequency=50
)
print(f"所需启动电容: {C_required*1e6:.2f} μF")
print(f"建议选用: {math.ceil(C_required*1e6/10)*10} μF 电解电容")
总结:复数让AC电路计算变得简单
说实话,用Python算复数比我当年手算快多了。以前一道题要算半页纸,现在敲几行代码就能出结果,还能顺便画个图看看频率响应。
核心要点回顾:
- Python里用
j表示虚数单位 - 电阻阻抗是实数,电感是正虚数,电容是负虚数
- 串联直接加,并联用导纳(1/Z)相加再取倒数
- 复功率 S = V × I*,实部是有功功率,虚部是无功功率
- 换频率计算阻抗,复数自动处理相位变化
下次你要算交流电路,别再用笔算了——打开Python,几分钟出结果,还有闲工夫喝口茶。
