複素数を扱う(complex, cmath)|Python
Python は複素数を組み込み型としてサポートしている。虚数単位は j で表し、3 + 4j のように書く。電気工学や信号処理、量子力学のシミュレーションなど、複素数を使う分野で役立つ。
複素数の作成
複素数リテラルは 実部 + 虚部j の形式で書く。
z = 3 + 4j
print(z) # (3+4j)
print(type(z)) # <class 'complex'>complex() 関数でも作成できる。
z1 = complex(3, 4) # 3 + 4j
z2 = complex(5) # 5 + 0j(実数)
z3 = complex('3+4j') # 文字列から(スペース不可)
print(z1) # (3+4j)文字列から作成する場合、+ の前後にスペースを入れると ValueError になるので注意。
実部と虚部の取得
real と imag 属性で実部・虚部を取り出せる。
z = 3 + 4j
print(z.real) # 3.0
print(z.imag) # 4.0どちらも float 型で返される。
四則演算
複素数同士の演算は数学の定義どおりに動作する。
a = 1 + 2j
b = 3 + 4j
print(a + b) # (4+6j)
print(a - b) # (-2-2j)
print(a * b) # (-5+10j) ← (1+2j)(3+4j) = 3+4j+6j+8j² = 3+10j-8 = -5+10j
print(a / b) # (0.44+0.08j)累乗も使える。j**2 は -1 になる。
print(1j ** 2) # (-1+0j)
print((1 + 1j) ** 2) # 2j共役複素数と絶対値
conjugate() メソッドで共役複素数を取得する。abs() 関数で絶対値(複素平面上の原点からの距離)を求められる。
z = 3 + 4j
print(z.conjugate()) # (3-4j)
print(abs(z)) # 5.0 ← √(3² + 4²) = 5cmath モジュール
標準ライブラリの cmath は複素数向けの数学関数を提供する。math モジュールの関数は複素数に対応していないため、複素数を扱うときは cmath を使う。
import cmath
z = 1 + 1j
# 平方根
print(cmath.sqrt(z)) # (1.0986841134678098+0.4550898605622274j)
# 指数関数
print(cmath.exp(z)) # (1.4686939399158851+2.2873552871788423j)
# 自然対数
print(cmath.log(z)) # (0.34657359027997264+0.7853981633974483j)負の数の平方根も計算できる。
import cmath
print(cmath.sqrt(-1)) # 1j
print(cmath.sqrt(-4)) # 2jmath.sqrt(-1) は ValueError になるが、cmath.sqrt(-1) は虚数を返す。
極形式への変換
複素数は直交形式()と極形式()で表現できる。cmath.polar() で極形式に変換し、cmath.rect() で直交形式に戻す。
import cmath
z = 1 + 1j
# 極形式に変換(絶対値 r, 偏角 θ)
r, theta = cmath.polar(z)
print(f'r = {r}, θ = {theta}') # r = 1.414..., θ = 0.785...(π/4)
# 直交形式に戻す
z2 = cmath.rect(r, theta)
print(z2) # (1.0000000000000002+1j)偏角はラジアンで返される。cmath.phase() で偏角だけを取得することもできる。
オイラーの公式
オイラーの公式 を Python で確認してみよう。
import cmath
result = cmath.exp(1j * cmath.pi) + 1
print(result) # (1.2246467991473532e-16+0j)厳密には 0 だが、浮動小数点数の誤差により極めて小さな値になる。実質ゼロと見なせる。
使用例:交流回路のインピーダンス
電気工学では複素数を使ってインピーダンスを表現する。抵抗 、コイルのリアクタンス 、コンデンサのリアクタンス を組み合わせたインピーダンス は次のように計算できる。
import cmath
R = 100 # 抵抗(Ω)
XL = 50 # 誘導性リアクタンス(Ω)
XC = 30 # 容量性リアクタンス(Ω)
# インピーダンス Z = R + j(XL - XC)
Z = complex(R, XL - XC)
print(f'インピーダンス: {Z}') # (100+20j)
# 絶対値と位相
print(f'|Z| = {abs(Z):.2f} Ω') # 102.00 Ω
print(f'位相 = {cmath.phase(Z):.4f} rad') # 0.1974 rad複素数を使うことで、振幅と位相を同時に扱える。交流回路の解析が格段にシンプルになる。



