Python复数类型complex应用场景详解

一、开篇:Python内置复数——一个被低估的特性
如果你不是数学或物理专业的,可能从高中毕业后就没再接触过复数。你可能会想:“我写程序永远用不到复数吧?”
不一定。复数在信号处理、图像处理、电子电路仿真、量子计算、3D图形学等领域都有实际应用。而Python是为数不多的内置复数类型的主流编程语言——在很多语言中你需要引入第三方库才能处理复数。
⌨️ 这篇文章有两个目的:一是让你了解Python中的复数怎么用,二是让你知道它在什么场景下有用。即使你平时用不到,了解Python有这个内置能力也是一件好事。
二、复数的数学基础回顾
2.1 5分钟复习复数
复数由两部分组成:实部(real part) 和 虚部(imaginary part)。形如:
a + bj (在数学中通常写作 a + bi,Python中用 j 代替 i)
其中:
a是实部(一个实数)b是虚部系数(一个实数)j是虚数单位,满足 j² = -1
# Python中的复数 z1 = 3 + 4j # 实部=3, 虚部=4 z2 = 1 - 2j # 实部=1, 虚部=-2 z3 = 5j # 纯虚数,实部=0(注意:不能写成 j5) z4 = 2 + 0j # 其实就是实数2(但类型是complex)
⚠️ 注意:Python中使用 j 而不是数学中的 i 来表示虚数单位。这是工程领域的惯例(因为 i 常被用作电流的符号)。
三、Python中复数的创建
3.1 字面量方式
# 基本创建 a = 3 + 4j b = -1 - 2j c = 5j # 等于 0 + 5j d = 2 - 0j # 等于 2 + 0j # 注意:虚部系数必须紧挨着j # e = 1 + j # NameError!j被当作变量名 e = 1 + 1j # OK
3.2 使用complex()函数
# 从一个参数
z1 = complex(5) # (5+0j)
z2 = complex(3.14) # (3.14+0j)
# 从两个参数(实部, 虚部)
z3 = complex(3, 4) # (3+4j)
z4 = complex(-1, 2.5) # (-1+2.5j)
# 从字符串(不能有空格!)
z5 = complex('3+4j') # (3+4j)
z6 = complex('-1-2j') # (-1-2j)
z7 = complex('5j') # 5j
z8 = complex('3') # (3+0j)
# 这些会报错
# complex('3 + 4j') # 字符串中有空格!
# complex('3+4i') # Python用j,不是i
3.3 获取实部和虚部
z = 3 + 4j print(z.real) # 3.0(注意:返回float类型) print(z.imag) # 4.0 # 复数的共轭(虚部取反) print(z.conjugate()) # (3-4j)
四、复数的运算
4.1 基本算术运算
a = 3 + 4j b = 1 - 2j # 加法:(3+4j) + (1-2j) = 4+2j print(a + b) # (4+2j) # 减法:(3+4j) - (1-2j) = 2+6j print(a - b) # (2+6j) # 乘法:(3+4j)(1-2j) = 3-6j+4j-8j² = 3-2j+8 = 11-2j print(a * b) # (11-2j) # 除法:(3+4j)/(1-2j) print(a / b) # (-1+2j) # 幂运算 print(a ** 2) # (-7+24j) — 因为 (3+4j)² = 9+24j+16j² = 9+24j-16 = -7+24j
4.2 比较运算
a = 3 + 4j b = 3 + 4j # 可以比较相等 print(a == b) # True print(a != b) # False # 不能比较大小! # print(a > b) # TypeError: '>' not supported between complex numbers # print(a < b) # 同上
⚠️ 复数不能比较大小——这在数学上就没有意义。复数之间只能判断相等或不等。
4.3 内置函数对复数的支持
import math import cmath # 复数的数学函数 z = 3 + 4j # abs():复数的模(magnitude) # |3+4j| = sqrt(3² + 4²) = sqrt(25) = 5 print(abs(z)) # 5.0 # pow():幂运算 print(pow(z, 2)) # (-7+24j) # round()不能用于复数 # round(z) # TypeError # cmath模块:复数的数学函数 print(cmath.sqrt(z)) # (2+1j)(因为(2+j)² = 4+4j+j² = 3+4j) # 复数的极坐标表示 print(cmath.polar(z)) # (5.0, 0.9272952180016122) # 返回 (模, 辐角) = (5.0, arctan(4/3)) # 从极坐标恢复复数 modulus, angle = 5.0, 0.9272952180016122 print(cmath.rect(modulus, angle)) # (3+4j) # 欧拉公式:e^(jx) = cos(x) + j*sin(x) x = 0.5 print(cmath.exp(1j * x)) # (0.87758+0.47943j) print(complex(cmath.cos(x), cmath.sin(x))) # 手动计算验证
4.4 cmath模块常用函数
import cmath
z = 1 + 1j
# 指数和对数
print(cmath.exp(z)) # e^z
print(cmath.log(z)) # ln(z)
print(cmath.log10(z)) # log10(z)
# 三角函数
print(cmath.sin(z))
print(cmath.cos(z))
print(cmath.tan(z))
# 反三角函数
print(cmath.asin(z))
print(cmath.acos(z))
print(cmath.atan(z))
# 双曲函数
print(cmath.sinh(z))
print(cmath.cosh(z))
print(cmath.tanh(z))
# 判断函数
print(cmath.isinf(complex(float('inf'), 0))) # True
print(cmath.isnan(complex(float('nan'), 0))) # True
print(cmath.isclose(1+2j, 1+2.0000000001j)) # True
五、复数的实际应用场景
5.1 信号处理:傅里叶变换
import cmath
def discrete_fourier_transform(samples):
"""
离散傅里叶变换(DFT)
输入:时域信号采样点列表(实数)
输出:频域复数列表
"""
n = len(samples)
result = []
for k in range(n):
# 计算第k个频率分量
frequency_component = 0j
for t in range(n):
angle = -2 * cmath.pi * 1j * k * t / n
frequency_component += samples[t] * cmath.exp(angle)
result.append(frequency_component)
return result
# 示例:分析一个包含两个频率成分的信号
import math
# 生成采样信号:50Hz + 120Hz的正弦波
sample_rate = 500 # 采样率
duration = 1.0 # 1秒
n_samples = int(sample_rate * duration)
samples = []
for i in range(n_samples):
t = i / sample_rate
value = math.sin(2 * math.pi * 50 * t) + 0.5 * math.sin(2 * math.pi * 120 * t)
samples.append(value)
# 执行DFT
frequency_spectrum = discrete_fourier_transform(samples)
# 显示前10个频率分量的幅度
print('频率分析结果:')
for i in range(10):
magnitude = abs(frequency_spectrum[i])
frequency = i * sample_rate / n_samples
print(f'{frequency:.0f}Hz: 幅度={magnitude:.2f}')
5.2 图像处理:复数表示像素值
# 在图像处理中,可以使用复数来表示二维坐标系中的点
# 复数的实部表示x坐标,虚部表示y坐标
def rotate_point(x, y, angle_degrees):
"""用复数实现二维平面上的点旋转"""
# 创建表示点的复数
point = complex(x, y)
# 创建旋转因子:e^(jθ) = cos(θ) + j*sin(θ)
import math
angle_radians = math.radians(angle_degrees)
rotation = complex(math.cos(angle_radians), math.sin(angle_radians))
# 旋转:复数乘法
rotated = point * rotation
return rotated.real, rotated.imag
# 测试:将点(1, 0)旋转90度
x, y = rotate_point(1, 0, 90)
print(f'(1, 0)旋转90度后:({x:.2f}, {y:.2f})') # (0.00, 1.00)
# 放大/缩小
def scale_point(x, y, factor):
"""缩放点"""
point = complex(x, y)
scaled = point * factor
return scaled.real, scaled.imag
x, y = scale_point(3, 4, 2)
print(f'(3, 4)放大2倍:({x}, {y})') # (6.0, 8.0)
5.3 电路分析:阻抗计算
# 在交流电路分析中,阻抗(电阻+电抗)用复数表示
# Z = R + jX
# R:电阻(实部),X:电抗(虚部)
# 电感:X_L = jωL,电容:X_C = 1/(jωC) = -j/(ωC)
def impedance_resistor(r):
"""纯电阻阻抗"""
return complex(r, 0)
def impedance_inductor(inductance, frequency):
"""电感阻抗:Z_L = jωL"""
omega = 2 * 3.14159 * frequency
return complex(0, omega * inductance)
def impedance_capacitor(capacitance, frequency):
"""电容阻抗:Z_C = 1/(jωC)"""
omega = 2 * 3.14159 * frequency
return complex(0, -1 / (omega * capacitance))
def parallel_impedance(z1, z2):
"""并联阻抗"""
return (z1 * z2) / (z1 + z2)
def series_impedance(*impedances):
"""串联阻抗"""
return sum(impedances)
# 示例:RLC串联电路
R = 100.0 # 100欧姆电阻
L = 0.1 # 100毫亨电感
C = 10e-6 # 10微法电容
f = 1000.0 # 1000Hz频率
Z_R = impedance_resistor(R)
Z_L = impedance_inductor(L, f)
Z_C = impedance_capacitor(C, f)
Z_total = series_impedance(Z_R, Z_L, Z_C)
print(f'总阻抗:{Z_total}')
print(f'阻抗模:{abs(Z_total):.2f}欧姆')
print(f'相位角:{cmath.phase(Z_total):.2f}弧度')
5.4 分形生成:曼德勃罗集
def mandelbrot(c, max_iterations=100):
"""
判断一个复数c是否属于曼德勃罗集
返回迭代次数(用于着色),如果在max_iterations内不发散则返回max_iterations
"""
z = 0j
for n in range(max_iterations):
z = z * z + c
if abs(z) > 2:
return n
return max_iterations
def generate_mandelbrot(width=80, height=40, max_iter=50):
"""生成曼德勃罗集的ASCII艺术"""
x_min, x_max = -2.0, 1.0
y_min, y_max = -1.0, 1.0
for y in range(height):
line = ''
for x in range(width):
# 将像素坐标映射到复数平面
real = x_min + (x / width) * (x_max - x_min)
imag = y_min + (y / height) * (y_max - y_min)
c = complex(real, imag)
# 计算这个点属于曼德勃罗集的程度
m = mandelbrot(c, max_iter)
# 用不同字符表示不同深度
if m == max_iter:
line += '#'
elif m > max_iter * 0.8:
line += '*'
elif m > max_iter * 0.5:
line += '+'
elif m > max_iter * 0.2:
line += '.'
else:
line += ' '
print(line)
# 生成曼德勃罗集(终端中的ASCII艺术)
generate_mandelbrot(100, 40)
六、复数的类型转换
# 复数 → 其他类型
z = 3 + 4j
# 复数 → 字符串
print(str(z)) # '(3+4j)'
# 复数 → 整数/浮点数?不行
# int(z) # TypeError
# float(z) # TypeError
# 但可以取模
magnitude = abs(z) # 5.0(float类型)
# 其他类型 → 复数
print(complex(5)) # (5+0j)
print(complex(3.14)) # (3.14+0j)
print(complex(3, 4)) # (3+4j)
print(complex('1+2j')) # (1+2j)
七、使用复数的注意事项
7.1 虚部符号问题
import cmath
# 对负数开方
# math.sqrt(-1) # ValueError
result = cmath.sqrt(-1) # 1j
print(result)
# 但cmath.sqrt返回复数
print(cmath.sqrt(4)) # (2+0j)——即使结果是实数,也返回complex类型
print(cmath.sqrt(-4)) # 2j——令人困惑的写法,实际是0+2j
# 如果你想要实数,需要检查
def safe_sqrt(x):
"""安全开方:正数返回float,负数返回complex"""
if x >= 0:
import math
return math.sqrt(x)
else:
return cmath.sqrt(x)
print(safe_sqrt(4)) # 2.0
print(safe_sqrt(-4)) # 2j
7.2 复数的实部和虚部都是float
z = 3 + 4j
print(type(z.real)) # <class 'float'>
print(type(z.imag)) # <class 'float'>
# 这意味着实部或虚部也可以是float中的特殊值
z1 = complex(float('inf'), 0) # (inf+0j)
z2 = complex(0, float('nan')) # (nanj)
print(z1, z2)
八、本篇小节
✅ Python内置复数类型——一个你可能不常用到但在需要时非常方便的特性:
- 创建方式:字面量
3+4j或complex(3, 4)或complex('3+4j') - 基本运算:加减乘除、幂运算都支持,但不能比较大小
- cmath模块:提供复数的sin、cos、exp、log、sqrt等函数
- 实际应用:信号处理(傅里叶变换)、图像旋转、电路分析、分形生成
- 注意点:虚部系数必须紧挨j(
4j而不是4 j)、Python用j不是i
💡 复数是Python"内置电池"理念的又一个体现。你可能90%的日常开发中用不到它,但当你的项目涉及信号处理、科学计算或图形学的时候,Python不用你额外装任何库就能搞定复数运算。下一篇我们来学习布尔类型bool。
到此这篇关于Python复数类型complex应用场景详解的文章就介绍到这了,更多相关Python复数类型complex内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Python爬虫抓取豆瓣TOP250数据从分析到实践的全过程(详细图解)
本文介绍了使用Python爬取豆瓣电影Top250数据的方法,首先验证了目标数据在页面源代码中,然后通过requests模块获取页面内容,添加请求头绕过反爬机制,接着使用re模块编写正则表达式,采用惰性匹配模式提取信息,通过循环实现翻页爬取,将10页共250条数据保存为CSV文件2025-10-10
Python多进程通信Queue、Pipe、Value、Array实例
这篇文章主要介绍了Python多进程通信Queue、Pipe、Value、Array实例,queue和pipe用来在进程间传递消息、Value + Array 是python中共享内存映射文件的方法,需要的朋友可以参考下2014-11-11


最新评论