할선법 문서의 구현 코드다. if __name__ == "__main__": 아래가 자체 테스트다.

"""할선법 구현과 검증. 뉴턴 방법과 비교."""
import math


def secant(f, x_prev, x, n):
    out = [x_prev, x]
    for _ in range(n):
        fx, fp = f(x), f(x_prev)
        x_prev, x = x, x - fx * (x - x_prev) / (fx - fp)
        out.append(x)
    return out


def newton(f, df, x, n):
    out = [x]
    for _ in range(n):
        x = x - f(x) / df(x); out.append(x)
    return out


def main():
    f = lambda x: math.exp(-x) - x
    df = lambda x: -math.exp(-x) - 1
    root = 0.56714329040978387
    s = secant(f, 0.0, 1.0, 6)
    assert round(f(0.0), 5) == 1.0 and round(f(1.0), 5) == -0.63212
    assert round(s[2], 5) == 0.61270 and round(f(s[2]), 5) == -0.07081            # 문서 표
    assert round(s[3], 5) == 0.56384
    assert round(abs(root - s[2]) / root * 100, 1) == 8.0 and round(abs(root - s[3]) / root * 100, 2) == 0.58
    # 뉴턴 방법 표 (미분적분학 문서의 예)
    nw = newton(f, df, 0.0, 4)
    assert [round(v, 9) for v in nw] == [0.0, 0.5, 0.566311003, 0.567143165, 0.56714329]
    # 수렴 빠르기: 오차가 줄어드는 차수(log 비율). 뉴턴 약 2, 할선법 약 1.618
    def order(seq):
        e = [abs(v - root) for v in seq if abs(v - root) > 1e-14]
        return math.log(e[-1] / e[-2]) / math.log(e[-2] / e[-3])
    on, os_ = order(nw[:5]), order(secant(f, 0.0, 1.0, 5))
    assert 1.8 < on < 2.2 and 1.4 < os_ < 1.9
    print("수렴 차수 추정: 뉴턴", round(on, 2), "할선", round(os_, 2))
    # 할선법은 두 시작점이 근을 사이에 두지 않아도 된다
    s2 = secant(f, 2.0, 3.0, 8)
    assert f(2.0) * f(3.0) > 0 and abs(s2[-1] - root) < 1e-10
    # 분모가 0이 되는 실패: 두 점의 함수 값이 같을 때
    g = lambda x: x * x - 4
    try:
        secant(g, -1.0, 1.0, 1); raise RuntimeError
    except ZeroDivisionError:
        pass
    # 카드 C2: x² − 2, 시작 1과 2 → 4/3
    h = lambda x: x * x - 2
    assert abs(secant(h, 1.0, 2.0, 1)[-1] - 4 / 3) < 1e-15
    print("ALL CHECKS PASSED")


if __name__ == "__main__":
    main()