複素数を扱う(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 になるので注意。

実部と虚部の取得

realimag 属性で実部・虚部を取り出せる。

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²) = 5

cmath モジュール

標準ライブラリの 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))  # 2j

math.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

複素数を使うことで、振幅と位相を同時に扱える。交流回路の解析が格段にシンプルになる。