复数 complex
Python 原生支持复数类型 complex,后缀 j 或 J 表示虚数单位。复数在科学计算、信号处理、电路分析和某些工程领域有广泛应用。Python 将复数作为一等公民对待,可以直接进行算术运算,无需引入外部库。
创建复数
复数字面量由实部、虚部和一个 j 后缀组成:
# 纯虚数
z1 = 3j
print(z1) # 3j
# 实部+虚部
z2 = 3 + 4j
print(z2) # (3+4j)
# 使用 complex() 构造函数
z3 = complex(3, 4) # (3+4j)
z4 = complex(5) # (5+0j),省略虚部默认为 0
z5 = complex() # 0j,实部和虚部都默认为 0
z6 = complex("3+4j") # (3+4j),从字符串解析
注意:在字面量中,j 前面必须有数字或表达式,单独的 j 会被当作变量名:
# z = j # NameError: name 'j' is not defined
z = 1j # 正确
complex() 从字符串解析时,字符串中间不能有空格:
print(complex("3+4j")) # (3+4j)
# complex("3 + 4j") # ValueError,不能有空格
访问实部和虚部
复数对象提供 .real 和 .imag 两个只读属性访问实部和虚部,两者都返回浮点数:
z = 3 + 4j
print(z.real) # 3.0
print(z.imag) # 4.0
print(type(z.real)) # <class 'float'>
即使复数是纯虚数或纯实数,这两个属性依然可用:
print((5j).real) # 0.0
print((5j).imag) # 5.0
print((5+0j).imag) # 0.0
复数运算
复数支持完整的算术运算集,运算规则遵循数学定义:
a = 3 + 4j
b = 1 + 2j
print(a + b) # (4+6j)
print(a - b) # (2+2j)
print(a * b) # (-5+10j),(3*1-4*2) + (3*2+4*1)j
print(a / b) # (2.2-0.4j)
print(a ** 2) # (-7+24j)
复数与整数或浮点数混合运算时,非复数操作数会被提升为复数:
print((3 + 4j) + 2) # (5+4j)
print((3 + 4j) * 2.0) # (6+8j)
共轭与模
.conjugate() 方法返回共轭复数(虚部取反):
z = 3 + 4j
print(z.conjugate()) # (3-4j)
复数的模(绝对值)通过 abs() 计算,等于 sqrt(real^2 + imag^2):
z = 3 + 4j
print(abs(z)) # 5.0,sqrt(9+16)=5
cmath 模块提供了更多复数数学函数,如相位、极坐标转换、指数、对数、三角函数等:
import cmath
z = 3 + 4j
print(cmath.phase(z)) # 0.927295...,弧度制的相位角
print(cmath.polar(z)) # (5.0, 0.927295...),(模, 相位)
print(cmath.rect(5, 0.927)) # (3+4j),极坐标转直角坐标
print(cmath.exp(1j * cmath.pi)) # (-1+1.2246467991473532e-16j),欧拉公式
print(cmath.log(z)) # (1.6094379124341003+0.9272952180016122j)
print(cmath.sqrt(-1)) # 1j
比较与哈希
复数不支持大小比较(<、>、<=、>=),因为复数在数学上没有全序关系:
z = 3 + 4j
# z > 0 # TypeError: '>' not supported between instances of 'complex' and 'int'
但复数支持相等比较 == 和 !=:
print(3 + 4j == (3 + 4j)) # True
print(3 + 4j == 3 + 4.0001j) # False
由于复数不可哈希,不能作为字典的键或放入集合:
# {3 + 4j: "value"} # TypeError: unhashable type: 'complex'
如果需要将复数用作键,可以将其转换为字符串或元组 (real, imag)。
不可变性
与整数和浮点数一样,复数是不可变对象。任何运算都会产生新的复数对象,原对象保持不变:
z = 3 + 4j
w = z
z = z + 1
print(w) # (3+4j),w 仍指向原对象
实际应用场景
交流电路分析:阻抗计算涉及复数,电阻为实部,电抗为虚部:
# 串联 RLC 电路
R = 10 # 电阻 10 欧姆
L = 0.1 # 电感 0.1 亨利
C = 100e-6 # 电容 100 微法
f = 50 # 频率 50 Hz
omega = 2 * cmath.pi * f
Z_R = R
Z_L = 1j * omega * L
Z_C = 1 / (1j * omega * C)
Z_total = Z_R + Z_L + Z_C
print(f"总阻抗: {Z_total:.2f} 欧姆")
print(f"阻抗模: {abs(Z_total):.2f} 欧姆")
信号处理:傅里叶变换天然涉及复数,虽然实际工程中通常用 numpy 处理大规模数据,但理解 Python 原生复数有助于掌握底层概念。
二维旋转:复数乘法可以实现平面旋转:
import cmath
point = 3 + 4j # 平面上的点
angle = cmath.pi / 4 # 旋转 45 度
rotated = point * cmath.exp(1j * angle)
print(f"旋转后: {rotated}")
边界与注意事项
浮点数精度影响:复数的实部和虚部都是浮点数,因此同样受浮点精度限制:
z = 0.1 + 0.2j
w = 0.3 + 0j
print(z == w) # False,与浮点数精度问题相同
print(abs(z - w) < 1e-9) # True,用容差比较
字符串格式化:f-string 可以直接格式化复数:
z = 3 + 4j
print(f"{z}") # (3+4j)
print(f"{z.real:.2f}") # 3.00
类型检查:
print(isinstance(3 + 4j, complex)) # True
print(type(3 + 4j)) # <class 'complex'>
复数虽然是小众类型,但 Python 将其内置为原生类型,体现了"电池 included"的设计哲学。在需要处理二维平面、交流电路或频域分析的场景中,原生复数支持能显著简化代码。