콘텐츠로 이동

Python으로 검증하기

  • 식 하나를 SymPy 유도에서부터 페이지와 테스트까지 따라갑니다.
  • 두 계산을 상대 차이(relative difference)로 비교하고, 반올림으로는 실패하지 않고 실제 실수는 통과하지 못하는 허용오차(tolerance)를 고릅니다.
  • 이 사이트의 검사를 자신의 컴퓨터에서 실행합니다.

이 사이트의 모든 식은 packages/pe-core/equations/equations.yaml에 한 번씩, 기호와 테스트와 인용을 갖춘 SymPy 식으로 들어 있습니다. Python 패키지 python/pe_core는 이 파일을 바탕으로 동작합니다.

  • 가능한 경우 python/pe_core/derive/의 스크립트가 회로의 평형 방정식(balance equation)을 SymPy로 한 단계씩 풀어 식을 기본 원리에서 유도합니다. 유도 과정 페이지는 코드가 계산한 그대로 그 단계를 보여 주며, pytest는 각 결과가 카탈로그의 식과 같은지 확인합니다.
  • python scripts/gen_equations.py는 페이지에 보이는 LaTeX와 테스트 벡터(test vector), 곧 각 식의 자체 테스트와 SymPy로 계산한 무작위 입력을 만듭니다. CI는 이를 다시 실행해 조금이라도 다르면 실패합니다.

페이지와 도구가 쓰는 TypeScript 엔진은 같은 파일에서 생성하지 않고 손으로 따로 쓴 계산 함수를 가지고 있습니다. 한쪽의 실수가 다른 쪽으로 복사되지 않게 하기 위해서입니다. vitest는 모든 계산 함수를 테스트 벡터와 비교합니다.

두 계산은 상대 차이로 비교합니다.

δ=∣x−xref∣∣xref∣\delta = \frac{\left|{x - x_\mathrm{ref}}\right|}{\left|{x_\mathrm{ref}}\right|}
δ\delta
상대 차이
xrefx_\mathrm{ref}
기준값
xx
검사할 값
기준값에 대한 값의 상대 차이✓ 테스트 8개로 검증됨
가정, 표기 규약, 출처
가정
  • 정의
비고
볼트를 밀리볼트로 바꾸듯 물리량의 배율을 바꿔도 상대 차이는 달라지지 않으므로, 하나의 허용오차를 모든 물리량에 쓸 수 있습니다(켈빈에 대한 섭씨처럼 영점이 옮겨 가는 단위는 예외). 기준값이 0이면 정의되지 않고, 0에 가까우면 작은 절대 차이가 큰 상대 차이가 됩니다. 이 사이트는 같은 식의 TypeScript와 Python 계산에 1e-9를, 식에 대한 시뮬레이션에 1 % 또는 2 %를 요구합니다
출처
Higham 2002, Sec. 1.2 (Relative Error and Significant Digits)
수식 id
num.rel_diff · equations.yaml 항목

상대 차이는 볼트를 밀리볼트로 바꾸듯 물리량의 배율을 바꿔도 달라지지 않으므로, 하나의 허용오차를 모든 양에 쓸 수 있습니다. 기준값이 0이면 정의되지 않고 [Higham 2002, Sec. 1.2], 0에 가까우면 작은 차이를 부풀리므로 그곳에서는 척도와 비교합니다. 올바른 두 프로그램이라도 비트까지 같은 결과를 내지는 않을 수 있습니다. 연산마다 결과를 반올림하고, 그 결과는 연산 순서에 따라 달라지기 때문입니다. 반올림 한 번이 수를 바꾸는 양은 그 수의 크기에 대한 비율로 많아야 수치 형식의 단위 반올림 오차(unit roundoff)입니다.

u=β1−p2u = \frac{\beta^{1 - p}}{2}
uu
단위 반올림 오차(unit roundoff)
β\beta
밑(이진수는 2)
pp
정밀도(가수의 자릿수)
부동소수점 형식의 단위 반올림 오차✓ 테스트 8개로 검증됨
가정, 표기 규약, 출처
가정
  • 형식에서 가장 가까운 수로 반올림(IEEE 754의 기본값)
비고
실수를 형식에서 가장 가까운 수로 반올림하면 값은 (정규 범위에서) 최대 원래 값의 이 비율만큼 바뀝니다. JavaScript의 수와 Python의 float가 쓰는 IEEE 754 배정밀도(binary64)는 밑이 2, 정밀도가 53자리이므로 u=2−53≈1.1×10−16u = 2^{-53} \approx 1.1 \times 10^{-16}입니다. Higham은 정밀도를 tt로 씁니다
출처
Higham 2002, Ch. 2 (Floating Point Arithmetic: the unit roundoff, Sec. 2.1, and its value in IEEE double precision)
수식 id
num.unit_roundoff · equations.yaml 항목

이 사이트는 한 식에 대한 TypeScript와 Python 계산이 10억분의 1 안에서 맞기를 요구합니다. 이는 단위 반올림 오차의 수백만 배이므로, 계산이 오차를 키우지 않는 한 반올림은 통과합니다. 거의 같은 두 수를 빼는 상쇄(cancellation)가 오차를 키우는 대표적인 경우입니다 [Higham 2002, Sec. 1.7]. 그래도 이 허용오차는 잘못된 상수나 빠진 인수 같은 실제 실수보다 훨씬 작습니다. 시뮬레이션을 그 식과 비교할 때는 허용오차가 더 느슨합니다. 식이 회로를 이상화하기 때문입니다. 식은 리플을 작다고 보며 [Erickson & Maksimović 2020, Ch. 2], SPICE 라이브러리의 스위치와 다이오드는 이상에 가까울 뿐입니다. SPICE 라이브러리의 값은 각 양의 주기 동안 최대 크기 대비 1 % 안에서 이상적인 식과 맞아야 하고, 브라우저 시뮬레이터의 변환비와 리플은 2 % 안에서 맞아야 합니다.

scripts/spice_crosscheck.py는 브라우저 시뮬레이터의 회로를 시뮬레이터의 식이 아니라 회로도로부터 넷리스트로 다시 작성해 ngspice로 실행합니다 [ngspice – open source SPICE simulator]. CI는 시뮬레이터를 ngspice의 결과와 비교합니다. 각 값은 주기 동안 그 양의 최대 크기 대비 0.5 % 안에서, SPICE 부품이 더하는 몫만큼의 작은 여유를 두고 맞아야 하며, 각 피크-피크 값은 2 % 안에서 맞아야 합니다.

시뮬레이션한 변환비를 이상적인 변환비와 비교하고, JavaScript의 수와 Python의 float가 쓰는 IEEE 754 배정밀도(binary64)의 단위 반올림 오차를 구합니다.

교차 검사 예제
기호값구하는 방법
xx 검사할 값0.496주어진 값
xrefx_\mathrm{ref} 기준값0.5주어진 값
β\beta 밑(이진수는 2)2주어진 값
pp 정밀도(가수의 자릿수)53주어진 값
δ\delta 상대 차이0.008기준값에 대한 값의 상대 차이
uu 단위 반올림 오차(unit roundoff)1.11e-16부동소수점 형식의 단위 반올림 오차

변환비는 이상적인 값과 0.008만큼 달라, 라이브러리의 1 % 안에 듭니다. 단위 반올림 오차는 1.11e-16이므로, 10억분의 1이라는 허용오차에는 수백만 번의 반올림이 들어갈 여유가 있습니다.

▶ 수식 탐색기에서 열기: 기준값에 대한 값의 상대 차이
초기값을 가져온 예제 num-parity

검사할 값을 바꿔 봅니다. 상대 차이는 기준값 양쪽에서 직선으로 커지고, 기준값에서만 0이 됩니다.

벤치에서 멀티미터로 컨버터의 입력 전압과 출력 전압을 재고, 그 비가 이상적인 변환비와 얼마나 다른지 Python으로 상대 차이를 계산한 뒤, 그 차이를 설명할 수 있는 것들을 적습니다. 다이오드의 전압 강하, 스위치와 권선의 저항, 리플 등입니다. 그런 다음 부하를 바꿔 그중 어느 것이 전류와 함께 커지는지 봅니다.

  • 기준값이 0에 가까우면 상대 차이는 의미가 없습니다. 라이브러리의 검사처럼 한 주기 동안의 최대 크기 같은 척도와 비교합니다.
  • 코드를 공유하는 두 구현은 그 실수도 공유합니다. 생성한 계산 함수는 원본 파일이 틀린 곳에서도 그 파일과 맞아 버립니다.
  • 부동소수점(floating-point) 수는 같은지를 비교하지 않습니다. binary64에서 0.1 + 0.1 + 0.1은 0.3이 아닙니다. 허용오차 안에 드는지로 비교합니다 (단위 반올림 오차).
  • 도구 SymPy: Solve Equations — the SymPy development team · 확인일 2026-09-25
    SymPy로 방정식이나 연립방정식을 기호에 대해 푸는 방법. 이 사이트의 유도 스크립트도 이 방법으로 평형 방정식을 풉니다.
  • 기술 기사 Floating-Point Arithmetic: Issues and Limitations — the Python documentation (the tutorial) · 확인일 2026-09-25
    컴퓨터에서 0.1 + 0.1 + 0.1이 0.3이 아닌 이유, 연산마다 최대 2**53분의 1의 반올림 오차가 더해질 수 있는 이유, 그리고 결과를 같은지가 아니라 허용오차 안에 드는지로 비교하는 이유.
  1. 이 사이트에 보이는 식은 어디에서 옵니까?

    1. 각 페이지에 손으로 입력한 LaTeX
    2. equations.yaml의 항목 하나: 기호, 테스트, 인용을 갖춘 SymPy 식
    3. TypeScript 엔진
    4. 퀴즈 파일
    정답과 해설

    정답: B 생성기가 그 항목에서 LaTeX와 테스트 벡터를 만들고, 커밋된 파일이 생성 결과와 다르면 CI가 실패합니다.

  2. TypeScript 계산 함수를 equations.yaml에서 생성하지 않고 손으로 쓰는 이유는 무엇입니까?

    1. 한쪽의 실수가 다른 쪽으로 복사되지 않게: 독립된 두 구현이 서로 맞아야 한다
    2. TypeScript는 YAML을 읽을 수 없어서
    3. 페이지를 빨리 불러오려고
    4. SymPy는 수를 계산할 수 없어서
    정답과 해설

    정답: A 생성한 코드는 원본이 틀린 곳에서도 원본과 맞아 버립니다. 독립된 구현은 스스로 테스트 벡터와 맞아야 합니다.

  3. 시뮬레이션한 변환비 0.495를 이상적인 0.5와 비교합니다. 상대 차이는 얼마입니까?

    1. 0.5 %
    2. 0.005 %
    3. 10 %
    4. 1 %
    정답과 해설

    정답: D 차이 0.005를 기준값 0.5로 나누면 0.01, 곧 1 %입니다.

  4. binary64의 단위 반올림 오차는 약 1.1e-16입니다. 일치 검사의 허용오차가 단위 반올림 오차가 아니라 10억분의 1인 이유는 무엇입니까?

    1. JavaScript가 Python보다 정밀도가 낮아서
    2. 올바른 두 계산도 연산마다 다르게 반올림해 단위 반올림 오차의 몇 배만큼 다를 수 있다. 10억분의 1은 그 여유를 주면서도 실제 실수를 잡는다
    3. 식이 10억분의 1까지만 알려져 있어서
    4. YAML이 더 작은 수를 담을 수 없어서
    정답과 해설

    정답: B 10억분의 1은 단위 반올림 오차의 수백만 배이므로 반올림 오차를 키우지 않는 계산에서 반올림은 통과하지만, 잘못된 상수나 인수는 훨씬 큽니다.

  5. 기준값이 0에 가까우면 상대 차이를 쓸 수 없는 이유는 무엇입니까?

    1. 0에 가까운 기준값으로 나누면 아주 작은 절대 차이도 엄청나게 커 보인다
    2. 0에는 단위가 없어서
    3. 그곳에서는 늘 0이어서
    4. 쓸 수 있다
    정답과 해설

    정답: A 그곳에서는 라이브러리의 검사처럼 한 주기 동안의 최대 크기 같은 척도와 비교합니다.

  6. Python에서 0.1 + 0.1 + 0.1 == 0.3의 값은 무엇입니까?

    1. True
    2. 오류
    3. False: 합이 0.3과 다른 배정밀도 수로 반올림된다
    4. 어떤 컴퓨터에서만 True
    정답과 해설

    정답: C 0.1은 이진수로 정확하지 않으며, 셋을 더해 반올림한 0.30000000000000004는 0.3 바로 옆의 배정밀도 수입니다. 허용오차 안에 드는지로 비교합니다.

이 사이트의 예제, 프리셋, 연습 문제에 나오는 수치는 교육용으로 만든 어림수(합성 값)이며, 실제 설계의 데이터가 아닙니다.