2.39. 부동소수점 다루기

부동소수점 숫자는 평범한 소수처럼 보이지만, 그중 몇 가지 동작은 이를 처음 접하는 사람을 놀라게 합니다. 그리고 그 동작 중 하나는 데스크톱 Python보다 MicroPython에서 더 두드러집니다. 이 페이지는 무엇을 예상해야 하는지, 그리고 조용히 오작동하지 않는 부동소수점 코드를 어떻게 작성하는지 다룹니다.

2.39.1. 정밀도

Python의 float 는 IEEE 754 이진 부동소수점 숫자입니다. 대부분의 MicroPython 빌드에서는 단정밀도 (32비트)인 반면, 데스크톱 CPython은 배정밀도 (64비트)를 사용합니다. 단정밀도는 약 7자리의 십진 정확도를, 배정밀도는 약 15자리를 가집니다.

>>> 0.1 + 0.2
0.3000000

>>> 1.0 / 3.0
0.3333333

>>> 1e30 * 1e30
inf

표현 가능한 범위도 양쪽 끝에서 더 좁습니다. 크기가 약 3.4e38 보다 큰 숫자는 inf 로 오버플로하고, 약 1.2e-38 보다 작은 숫자는 0으로 반올림됩니다.

2.39.2. 부동소수점 비교하기

가장 흔한 함정은 == 로 동등성을 검사하는 것입니다:

>>> 0.1 + 0.2 == 0.3
False

두 표현식 모두 같아야 할 것처럼 보이지만, 0.1 + 0.2 의 결과는 가장 가까운 표현 가능한 값이며 정확히 0.3 은 아닙니다. 대신 허용 오차 검사 를 사용하세요. 두 부동소수점이 동일한지가 아니라 충분히 가까운지를 묻는 것입니다:

if abs(a - b) < 1e-6:
    # close enough
    ...

허용 오차의 선택은 값의 규모에 따라 달라집니다. 숫자가 1 정도의 크기일 때는 고정된 1e-6 이 잘 동작하고, 값이 여러 자릿수에 걸쳐 변할 때는 상대 허용 오차가 더 낫습니다.

math.isclose() 는 두 가지를 한 번에 처리합니다:

from math import isclose

isclose(0.1 + 0.2, 0.3)         # True
isclose(1.0e6 + 1, 1.0e6)       # True (within default tolerance)

두 키워드 인자는 어떤 종류의 “가까움”을 인정할지 제어합니다:

  • rel_tol상대 허용 오차, 기본값 1e-9. 두 값의 차이가 더 큰 값의 이 비율 이내이면 일치하는 것으로 봅니다. 어떤 규모에서든 일반적인 비교에 적합합니다.

  • abs_tol절대 허용 오차, 기본값 0. 두 값의 차이가 이 고정된 양 이내이면 일치하는 것으로 봅니다.

math.isclose() 는 두 허용 오차 중 하나라도 충족되면 True 를 반환합니다. 0이 아닌 숫자 쌍 대부분에는 기본값이 적절하지만, 함정은 값 중 하나가 정확히 0일 수 있는 경우입니다. 상대 허용 오차 검사는 “차이 ≤ rel_tol × 가장 큰 값”으로 계산되는데, 가장 큰 값이 0이면 검사가 항상 실패합니다:

>>> isclose(0.0, 1e-12)
False

절대 허용 오차 검사에는 그런 문제가 없습니다. 0이 비교 대상이 될 수 있는 값이라면 언제든 abs_tol 을 전달하세요:

>>> isclose(0.0, 1e-12, abs_tol=1e-9)
True

2.39.3. 누적 오차

부동소수점의 긴 합산은 CPython보다 MicroPython에서 정밀도를 더 빨리 잃습니다. 모든 중간 결과가 32비트 정밀도로 다시 반올림되기 때문입니다:

total = 0.0
for _ in range(1000000):
    total += 0.1

print(total)        # noticeably off from 100000.0

정확도가 중요한 반복 덧셈에는 두 가지 패턴이 도움이 됩니다:

  • 정수로 누적하기 – 값을 정수로 환산할 수 있을 때마다 사용합니다. 초 대신 밀리초로, 볼트 대신 밀리볼트로 작업한 다음 마지막에 한 번만 변환합니다.

  • 더 작은 묶음으로 계산하기 – 묶음 결과를 합산하여 각 덧셈이 비슷한 크기의 값들 사이에서 이루어지도록 합니다.

정수 쪽에는 그런 한계가 없습니다. MicroPython 정수는 CPython과 마찬가지로 임의 정밀도입니다. 선택할 수 있는 경우, 정밀도 손실이 누적될 만한 작업에는 정수 산술을 선호하세요.