함수 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.
"""함수의 정의와 자연 정의역 검증.
문서: 01.함수 (예시, 카드 C2·C3, 자주 하는 오해)
주장 1: 유한한 대응(순서쌍 목록)이 함수인지는 "정의역의 모든 입력에 출력이 정확히 하나"로 판정한다.
주장 2: f(x) = sqrt(x - 1) / (x - 3)의 자연 정의역은 [1, 3) ∪ (3, ∞)이다.
주장 3: 파이썬은 정의역 밖의 입력을 오류로 알린다 (math.sqrt(-1) -> "math domain error").
주장 4: 같은 식 x^2도 정의역이 다르면 다른 함수다 (일대일 여부가 달라진다).
"""
import math
import random
def is_function(pairs, domain):
"""pairs: (입력, 출력) 목록. domain의 모든 원소에 출력이 정확히 하나면 True."""
outs = {}
for x, y in pairs:
outs.setdefault(x, set()).add(y)
return all(len(outs.get(x, set())) == 1 for x in domain)
def f(x):
return math.sqrt(x - 1) / (x - 3)
def defined(x):
try:
f(x)
return True
except (ValueError, ZeroDivisionError):
return False
def main():
# 주장 1: 카드 C2 (a)(b)를 작은 예로
people = {"민지": "03-14", "도윤": "07-01", "서연": "03-14"}
birthday = [(p, d) for p, d in people.items()]
assert is_function(birthday, people) # 사람 -> 생일: 함수
inverse = [(d, p) for p, d in people.items()]
assert not is_function(inverse, {"03-14", "07-01", "12-25"}) # 생일 -> 사람: 아님
# (c) x -> x^2 + y^2 = 1을 만족하는 y: x = 0에서 y = ±1, x = 2에서 없음
circle = [(0, 1), (0, -1)]
assert not is_function(circle, {0, 2})
# (d) 같은 입력에 매번 다른 출력
g = lambda x: random.random() + x
assert g(1) != g(1)
print("[OK] 카드 C2: 사람->생일 함수, 생일->사람·원·random 아님")
# 주장 2: 자연 정의역 [1, 3) ∪ (3, ∞)
grid = [i / 100 for i in range(-500, 1001)]
for x in grid:
expected = (1 <= x < 3) or (x > 3)
assert defined(x) == expected, x
assert defined(1) and not defined(3) and not defined(0.999)
print("[OK] 카드 C3: 자연 정의역 [1, 3) ∪ (3, ∞) — 격자 1,501점 전수 확인")
# 주장 3: 정의역 밖 입력의 오류 메시지
try:
math.sqrt(-1)
raise AssertionError
except ValueError as e:
assert str(e) in ("math domain error", "expected a nonnegative input, got -1.0"), str(e)
print(f"[OK] math.sqrt(-1) -> ValueError: {e}")
# 주장 4: x^2은 실수 전체에서 일대일이 아니고, [0, ∞)에서는 일대일이다
assert (-2) ** 2 == 2 ** 2
xs = [i / 10 for i in range(0, 101)]
assert len({x * x for x in xs}) == len(xs)
print("[OK] 오해: x^2은 정의역 ℝ에서 f(-2) = f(2), [0, ∞)에서는 서로 다른 입력이 서로 다른 출력")
print("ALL CHECKS PASSED")
if __name__ == "__main__":
main()