35. 실수 값의 오차
1. 키워드
- 부동소수점(Floating Point)
- 머신 엡실론(Machine Epsilon)
2. 실수 값의 오차
- 파이썬에서
0.1 + 0.2
의 값으로 0.3
이 나올 것 같지만 실제로는 0.30000000000000004
가 나온다.
- 파이썬은 실수를 부동소수점 방식으로 표현하는데 실수는 유한개의 비트로 정확하게 표현할 수 없다.
- 따라서 실수는 유한개의 비트를 사용하여 근삿값으로 표현한다.
- 즉,
0.30000000000000004
는 0.3
을 표현한 근삿값이다.
1) 두 실수가 같은지 판단하기
- 만약 두 실수가 같은지 판단할 때는
==
을 사용하면 안 되는데, 다음과 같이 0.1 + 0.2
와 0.3
은 같지 않다고 나온다.
>>> 0.1 + 0.2 == 0.3
False
0.1 + 0.2
는 0.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