역함수 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.
"""역함수 검증.
문서: 03.역함수 (예시, 예제, 카드 C2·C3, 자주 하는 오해)
주장 1: 섭씨 -> 화씨 F = 1.8C + 32의 역함수는 C = (F - 32)/1.8이다.
주장 2: f(x) = (2x + 1)/(x - 3)의 역함수는 (3x + 1)/(x - 2)이고, 2는 f의 치역에 없다.
주장 3: x^2은 실수 전체에서 역함수가 없고, [0, ∞)로 자르면 sqrt가 역함수다.
주장 4: f^{-1}(x)와 1/f(x)는 다르다 (f(x) = x + 1, x = 1에서 0과 1/2).
"""
import math
import random
from fractions import Fraction as F
def main():
to_f = lambda c: F(9, 5) * c + 32
to_c = lambda t: (t - 32) / F(9, 5)
assert to_f(100) == 212 and to_c(212) == 100 and to_f(-40) == -40
for c in range(-100, 101):
assert to_c(to_f(c)) == c
print("[OK] 주장 1: 100°C -> 212°F -> 100°C, -40에서 두 눈금이 같다")
f = lambda x: (2 * x + 1) / (x - 3)
finv = lambda y: (3 * y + 1) / (y - 2)
rng = random.Random(2)
for _ in range(5000):
x = F(rng.randint(-1000, 1000), rng.randint(1, 50))
if x == 3:
continue
assert finv(f(x)) == x
y = F(rng.randint(-1000, 1000), rng.randint(1, 50))
if y == 2:
continue
assert f(finv(y)) == y
# f(x) = 2 <=> 2x + 1 = 2x - 6 <=> 1 = -6: 해가 없다
assert all(f(F(n, 7)) != 2 for n in range(-700, 700) if n != 21)
print("[OK] 카드 C2: f^{-1}(x) = (3x+1)/(x-2), 무작위 5,000쌍 왕복 일치, 2는 치역 밖")
assert (-3) ** 2 == 3 ** 2 # 일대일이 아니다
for i in range(0, 1000):
x = i / 10
assert math.isclose(math.sqrt(x * x), x)
print("[OK] 카드 C3: x^2은 f(-3) = f(3), [0, ∞)에서는 sqrt(x^2) = x")
g = lambda x: x + 1
ginv = lambda x: x - 1
assert ginv(1) == 0 and F(1, g(1)) == F(1, 2)
print("[OK] 오해: f(x) = x + 1에서 f^{-1}(1) = 0, 1/f(1) = 1/2")
print("ALL CHECKS PASSED")
if __name__ == "__main__":
main()