Skip to content

35. 실수 값의 오차


1. 키워드

  • 부동소수점(Floating Point)
  • 머신 엡실론(Machine Epsilon)


2. 실수 값의 오차

  • 파이썬에서 0.1 + 0.2의 값으로 0.3이 나올 것 같지만 실제로는 0.30000000000000004가 나온다.
  • 파이썬은 실수를 부동소수점 방식으로 표현하는데 실수는 유한개의 비트로 정확하게 표현할 수 없다.
  • 따라서 실수는 유한개의 비트를 사용하여 근삿값으로 표현한다.
  • 즉, 0.300000000000000040.3을 표현한 근삿값이다.


1) 두 실수가 같은지 판단하기

  • 만약 두 실수가 같은지 판단할 때는 ==을 사용하면 안 되는데, 다음과 같이 0.1 + 0.20.3은 같지 않다고 나온다.


>>> 0.1 + 0.2 == 0.3
False


  • 0.1 + 0.20.30000000000000004이므로 0.3과는 다르다.
  • 이렇게 실수를 근삿값으로 표현하면서 발생하는 문제를 부동소수점 반올림 오차라고 한다.
  • 따라서 실수를 비교할 때는 연산한 값과 비교할 값의 차이를 구한 뒤 sys.float_info.epsilon보다 작거나 같은지 판단해야 한다.


>>> import math, sys

>>> x = 0.1 + 0.2

>>> math.fabs(x - 0.3) <= sys.float_info.epsilon
True


  • x의 값 0.30000000000000004에서 0.3을 뺀 값이 sys.float_info.epsilon보다 작거나 같으므로 두 값은 같은 값이라 할 수 있다.
  • 특히 math.fabs를 사용하여 두 값의 차이를 절댓값으로 만들면 음수가 나오더라도 정상적으로 판단할 수 있다.
  • 여기서 sys.float_info.epsilon에 저장된 값을 머신 엡실론이라고 부르는데, 어떤 실수를 가장 가까운 부동소수점 실수로 반올림했을 때 상대 오차는 항상 머신 엡실론 이하이다.
  • 즉, 머신 엡실론은 반올림 오차의 상한값이며 연산한 값과 비교할 값의 차이가 머신 엡실론보다 작거나 같다면 두 실수는 같은 값이라고 할 수 있다.


  • 파이썬 3.5 이상부터는 두 실수가 같은지 판단할 때 math.isclose 함수를 사용하면 된다.


>>> import math

>>> math.isclose(0.1 + 0.2, 0.3)
True


2) Decimal로 정확하나 자릿수 표현하기

  • 반올림 오차가 없는 고정소수점을 사용하려면 decimal 모듈의 Decimal을 사용하면 된다.
  • Decimal은 숫자를 10진수로 처리하여 정확한 소수점 자릿수를 표현한다.


>>> from decimal import Decimal

>>> Decimal("0.1") + Decimal("0.2")
Decimal('0.3')


3) Fraction으로 분수 표현하기

  • 순환소수는 고정소수점이라도 정확히 표현할 수 없다.
  • 이때는 fractions 모듈의 Fraction을 사용하여 분수로 표현하면 된다.


>>> from fractions import Fraction

>>> Fraction("10/3")
Fraction(10, 3)

References