Python的complex是内置数值类型,不需要第三方库即可完成复数创建、算术运算和cmath数学函数调用。原文示例覆盖字面量、complex()构造、实部虚部读取、DFT、二维点旋转、RLC阻抗和曼德勃罗集。下面按代码实现组织这些要点,便于在脚本中逐段验证。
一、创建复数与读取实部虚部- z1 = 3 + 4j
- z2 = 1 - 2j
- z3 = 5j
- z4 = 2 + 0j
- # e = 1 + j # NameError,j必须紧挨系数
- e = 1 + 1j
- z5 = complex(5)
- z6 = complex(3, 4)
- z7 = complex('-1-2j')
- # complex('3 + 4j') # 字符串内不能有空格
- # complex('3+4i') # Python使用j,不是i
- z = 3 + 4j
- print(z.real) # 3.0
- print(z.imag) # 4.0
- print(z.conjugate()) # (3-4j)
复制代码 字面量创建时,虚部系数必须紧挨j,不能写成1 + j;complex(real, imag)接受两个参数,complex(字符串)则要求字符串中没有空格,并且虚数单位用j而不是i。z.real和z.imag返回float,conjugate()把虚部取反。
二、算术运算、abs与比较限制- a = 3 + 4j
- b = 1 - 2j
- print(a + b) # (4+2j)
- print(a - b) # (2+6j)
- print(a * b) # (11-2j)
- print(a / b) # (-1+2j)
- print(a ** 2) # (-7+24j)
- print(abs(a)) # 5.0
- print(pow(a, 2)) # (-7+24j)
- print(a == b) # False
- # print(a > b) # TypeError,复数不能比较大小
复制代码 加减乘除和幂运算都按复数规则进行。abs(a)计算模,3+4j的模为sqrt(3²+4²)=5.0。复数可以判断相等或不等,但不能使用大于、小于比较;原文也指出round()不能用于复数。
三、cmath模块、极坐标与安全开方- import cmath
- z = 3 + 4j
- print(cmath.sqrt(z)) # (2+1j)
- print(cmath.polar(z)) # (5.0, 0.9272952180016122)
- print(cmath.rect(5.0, 0.9272952180016122)) # (3+4j)
- x = 0.5
- print(cmath.exp(1j * x)) # (0.87758+0.47943j)
- print(cmath.sqrt(4)) # (2+0j)
- print(cmath.sqrt(-4)) # 2j
复制代码 cmath提供复数的sqrt、exp、log、log10、sin、cos、tan、asin、acos、atan、sinh、cosh、tanh,以及isinf、isnan、isclose等判断函数。polar()返回模和辐角,rect()从极坐标恢复复数。需要注意cmath.sqrt(4)返回(2+0j),即使结果是实数也仍是complex;cmath.sqrt(-4)返回2j,实际表示0+2j。原文用safe_sqrt区分正数走math.sqrt、负数走cmath.sqrt:- import math
- import cmath
- def safe_sqrt(x):
- if x >= 0:
- return math.sqrt(x)
- return cmath.sqrt(x)
- print(safe_sqrt(4)) # 2.0
- print(safe_sqrt(-4)) # 2j
复制代码
四、可落地场景:DFT、点旋转、RLC阻抗、分形
离散傅里叶变换把时域采样累加为频域复数,复数同时保存幅度和相位信息。原文示例用50Hz和120Hz正弦波叠加,采样率500、时长1秒,并输出前10个频率分量的幅度:- import cmath
- import math
- def discrete_fourier_transform(samples):
- n = len(samples)
- result = []
- for k in range(n):
- 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
- sample_rate = 500
- duration = 1.0
- 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)
- frequency_spectrum = discrete_fourier_transform(samples)
- for i in range(10):
- magnitude = abs(frequency_spectrum[i])
- frequency = i * sample_rate / n_samples
- print(f'{frequency:.0f}Hz: 幅度={magnitude:.2f}')
复制代码 二维点旋转可以把坐标写成复数,再乘以旋转因子e^(jθ)=cos(θ)+j*sin(θ)。原文把点(1,0)旋转90度,输出(0.00,1.00);缩放点则直接用复数乘以factor。- def rotate_point(x, y, angle_degrees):
- point = complex(x, y)
- angle_radians = math.radians(angle_degrees)
- rotation = complex(math.cos(angle_radians), math.sin(angle_radians))
- rotated = point * rotation
- return rotated.real, rotated.imag
- x, y = rotate_point(1, 0, 90)
- print(f'(1, 0)旋转90度后:({x:.2f}, {y:.2f})') # (0.00, 1.00)
复制代码 交流电路阻抗用Z=R+jX表示,电阻阻抗为complex(r,0),电感阻抗为jωL,电容阻抗为1/(jωC),即-j/(ωC)。串联阻抗用sum求和,并联阻抗用(z1*z2)/(z1+z2)。原文RLC参数为R=100.0、L=0.1、C=10e-6、f=1000.0:- def impedance_resistor(r):
- return complex(r, 0)
- def impedance_inductor(inductance, frequency):
- omega = 2 * 3.14159 * frequency
- return complex(0, omega * inductance)
- def impedance_capacitor(capacitance, frequency):
- omega = 2 * 3.14159 * frequency
- return complex(0, -1 / (omega * capacitance))
- def series_impedance(*impedances):
- return sum(impedances)
- R = 100.0
- L = 0.1
- C = 10e-6
- f = 1000.0
- Z_total = series_impedance(impedance_resistor(R), impedance_inductor(L, f), impedance_capacitor(C, f))
- print(f'总阻抗:{Z_total}')
- print(f'阻抗模:{abs(Z_total):.2f}欧姆')
- print(f'相位角:{cmath.phase(Z_total):.2f}弧度')
复制代码 曼德勃罗集用迭代z=z*z+c判断发散,|z|超过2即退出。原文用迭代次数映射ASCII字符,坐标范围为x_min=-2.0、x_max=1.0、y_min=-1.0、y_max=1.0,生成100x40的终端图形:- def mandelbrot(c, max_iterations=100):
- 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):
- 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)
- generate_mandelbrot(100, 40)
复制代码
五、类型转换与常见注意点- z = 3 + 4j
- print(str(z)) # '(3+4j)'
- # int(z) # TypeError
- # float(z) # TypeError
- print(complex(5)) # (5+0j)
- print(complex(3, 4)) # (3+4j)
- print(complex('1+2j')) # (1+2j)
- print(type(z.real)) # <class 'float'>
- print(type(z.imag)) # <class 'float'>
- z1 = complex(float('inf'), 0)
- z2 = complex(0, float('nan'))
- print(z1, z2)
复制代码 复数可以转成字符串,但不能直接用int()或float()转换;需要数值时可使用abs()取模。复数实部和虚部都是float,因此可以承载inf和nan。创建字符串形式时不能有空格,虚数单位必须是j。cmath.sqrt(-4)的输出2j容易让人误以为是整数,实际是0+2j。原文最后强调,complex适合信号处理、科学计算和图形学等场景,日常脚本不常用,但需要时无需额外安装库。
本文代码均取自原文示例,主要保留了创建、运算、cmath、DFT、点旋转、RLC阻抗、分形和类型转换的实现,可逐段在Python解释器中验证。 |