로피탈 정리와 증가 속도 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.
"""로피탈 정리와 증가 속도 검증.
문서: 09.로피탈 정리와 증가 속도 (예시, 정리, 예제, 활용, 카드 C1~C3, 자주 하는 오해)
주장 1: (e^x - 1 - x)/x² -> 1/2 (x -> 0).
주장 2: x ln x -> 0 (x -> 0+), (1 + a/x)^x -> e^a.
주장 3: ln x / x^0.1 -> 0이지만 느리다: x = 10^10에서 약 2.3, x = 10^100에서 약 2.3e-8.
주장 4: x^10 / 1.1^x -> 0 (로그로 계산).
주장 5: 로피탈을 0/0이 아닌 곳에 쓰면 틀린다: (x+1)/(x+2) -> 1/2인데 도함수의 비는 1.
주장 6: (e^x - 1)/x를 작은 x에서 그대로 계산하면 오차가 크고 math.expm1은 정확하다.
"""
import math
def main():
for k in range(2, 6):
x = 10.0 ** -k
assert abs((math.expm1(x) - x) / (x * x) - 0.5) < x
print("[OK] 주장 1·카드 C2")
for k in range(2, 12):
x = 10.0 ** -k
assert abs(x * math.log(x)) < 30 * x
for a in (1, 2, -1):
assert abs((1 + a / 1e7) ** 1e7 - math.exp(a)) < 1e-5 * math.exp(a) * 10
print("[OK] 주장 2")
r10 = math.log(1e10) / (1e10) ** 0.1
r100 = math.log(1e100) / (1e100) ** 0.1
assert f"{r10:.1f}" == "2.3" and f"{r100:.1e}" == "2.3e-08"
print(f"[OK] 주장 3: {r10:.2f}, {r100:.2e}")
ratio = lambda x: math.exp(10 * math.log(x) - x * math.log(1.1))
assert ratio(100) > 1e15 and ratio(1000) < 1e-10 and ratio(5000) < 1e-150
print("[OK] 주장 4")
assert abs((1e-9 + 1) / (1e-9 + 2) - 0.5) < 1e-8 and 1 / 1 == 1
print("[OK] 주장 5·카드 C3·오해")
x = 1e-12
naive = (math.exp(x) - 1) / x
good = math.expm1(x) / x
assert abs(naive - 1) > 1e-5 and abs(good - 1) < 1e-11
print(f"[OK] 주장 6: 그대로 {naive!r}, expm1 {good!r}")
print("ALL CHECKS PASSED")
if __name__ == "__main__":
main()