[Github blog] 부동소수점
문제
Python에서 실수형 (float)를 다룰 때 다음과 같은 오류가 발생할 수 있다.
1
2
3
4
5
6
>>> 0.1 * 3 == 0.3
False
>>> 1.2 - 0.1 == 1.1
False
>>> 0.1 * 0.1 == 0.01
False
눈으로 봤을 때는 전혀 이상이 없기 때문에 이러한 오류를 겪었을 때 많이 당황했었던 기억이 있다.
원인
실수 표현 방식[1]
컴퓨터는 모든 수를 0과 1로 이루어진 2진수로 표현하고, 이는 실수도 마찬가지이다.
실수를 표현하는 방식은 크게 2가지 방식이 있다.
- 고정 소수점 (fixed point) 방식
- 부동 소수좀 (floating point) 방식
그 중에서도 Python은 실수를 부동소수점으로 표현한다.
부동소수점[2]
부동 소수점 방식은 하나의 실수를 부호(sign), 가수(mantissa), 지수(exponent)로 나누어 표현하는 방식을 의미한다.
부호는 전체 수가 양수 또는 음수를 표현하고,
지수는 2의 지수를 나타내며,
가수는 소수 이하를 표시합니다.
해결[1][3]
decimal.Decimal, math.fsum(), round(), float.as_integer_ratio(), math.is_close() 등의 함수를 사용해 문제를 해결할 수 있다.
- decimal.Decimal: 숫자를 10진수로 처리하여 정확한 소수점 자릿수를 표현
1 2 3 4 5
>>> 0.1 + 0.2 == 0.3 False >>> from decimal import Decimal >>> Decimal('0.1') + Decimal('0.2') == Decimal('0.3') True
- round(): 숫자를 반올림해주는 내장 (built-in) 함수
1 2 3 4
>>> 0.1 + 0.1 + 0.1 == 0.3 False >>> round(0.1 + 0.1 + 0.1, 10) == round(0.3, 10) True
결론
쉽고 간단해 보이지만 관련된 개념이 없었을 당시에는 매우 찾기 어려운 오류였다.
오류가 발생하는 원인을 알았기 때문에, 위의 방식 외에도 필요와 목적에 맞게 알맞은 방식으로 해결 할 수 있을 것 같다.
참조 (References)
This post is licensed under CC BY 4.0 by the author.