복소수 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.
"""복소수 검증.
문서: 18.복소수 (예시, 정의, 정리, 예제, 활용, 카드 C1~C3, 자주 하는 오해)
주장 1: (2 + 3i)(1 - i) = 5 + i, (5 + i)/(1 - i) = 2 + 3i, |3 + 4i| = 5, z·z̄ = |z|².
주장 2: x² + 2x + 5 = 0의 근은 -1 ± 2i이다.
주장 3: 실수 계수 다항식의 켤레: p(z̄) = conj(p(z)). 그래서 실수가 아닌 근은 켤레 쌍으로 나온다.
주장 4: √(-4)·√(-9) = (2i)(3i) = -6 ≠ √36 = 6.
주장 5: 파이썬은 j를 허수 단위로 쓴다: (1j)**2 == -1, abs(3+4j) == 5.0.
주장 6: 카드 C1 — (1 + 2i)(3 - i) = 5 + 5i, (1 + 2i)/(3 - i) = (1 + 7i)/10.
"""
import cmath
import random
from fractions import Fraction as F
class Q:
"""유리수 복소수 (정확 계산)."""
def __init__(s, a, b=0): s.a, s.b = F(a), F(b)
def __add__(s, o): return Q(s.a + o.a, s.b + o.b)
def __mul__(s, o): return Q(s.a * o.a - s.b * o.b, s.a * o.b + s.b * o.a)
def conj(s): return Q(s.a, -s.b)
def norm2(s): return s.a * s.a + s.b * s.b
def __truediv__(s, o):
n = s * o.conj(); d = o.norm2()
return Q(n.a / d, n.b / d)
def __eq__(s, o): return (s.a, s.b) == (o.a, o.b)
def main():
assert Q(2, 3) * Q(1, -1) == Q(5, 1) and Q(5, 1) / Q(1, -1) == Q(2, 3)
assert abs(3 + 4j) == 5.0
z = Q(7, -2)
assert (z * z.conj()) == Q(z.norm2(), 0)
print("[OK] 주장 1: 곱·나눗셈·크기·켤레")
for r in (Q(-1, 2), Q(-1, -2)):
assert r * r + Q(2) * r + Q(5) == Q(0)
print("[OK] 주장 2: -1 ± 2i")
rng = random.Random(18)
for _ in range(2000):
coeffs = [rng.randint(-9, 9) for _ in range(rng.randint(1, 6))]
z = Q(rng.randint(-9, 9), rng.randint(-9, 9))
def p(w):
acc = Q(0)
for c in reversed(coeffs):
acc = acc * w + Q(c)
return acc
assert p(z.conj()) == p(z).conj()
print("[OK] 주장 3: 실수 계수 다항식 2,000개에서 p(z̄) = conj p(z)")
prod = cmath.sqrt(-4) * cmath.sqrt(-9)
assert prod == -6 and cmath.sqrt(36) == 6
print(f"[OK] 주장 4·카드 C3: √-4·√-9 = {prod}, √36 = 6")
assert (1j) ** 2 == -1
print("[OK] 주장 5")
assert Q(1, 2) * Q(3, -1) == Q(5, 5) and Q(1, 2) / Q(3, -1) == Q(F(1, 10), F(7, 10))
print("[OK] 카드 C1: 5 + 5i, (1 + 7i)/10")
print("ALL CHECKS PASSED")
if __name__ == "__main__":
main()