들어가며
파이썬을 하다보면 소수를 다룰 일이 정말 많이 있습니다. 관련하여 아래 파이썬 코드의 올바른 출력은 무엇일까요?
a = 0.1 + 0.1 + 0.1
b = 0.3
if a == b:
print("True")
else:
print("False")
얼핏 생각하면 당연히 True일 것 같지만, 사실 정답은 False입니다. 실제로 a의 값을 출력해보면 0.30000000000000004라는 값이 출력됩니다. 왜 이런 결과가 나온 것일까요?
왜 이런 일이 발생했을까요?
바로 컴퓨터 세계에서는 소수를 부동소수점으로 표현하기 때문입니다. 관련하여 파이썬에서도 IEEE 754 부동소수점 표준을 따르고 있습니다.
부동소수점을 사용하면 고정소수점 방식과 비교하여 적은 바이트로도 넓은 값을 표현할 수 있습니다. 하지만 단점으로는 근사한 오차가 발생할 수 있다는 단점이 있습니다.
따라서 부동소수점을 정의할 때는 정밀도(precision) 이라는 개념을 함께 사용합니다.
예를 들어 float 자료형의 정밀도가 6이라면 소수점 6자리까지의 값만 유효하다는 뜻입니다.
그래서 float32, float64, double 등 다양한 소수 자료형이 있는 이유가 바로 이 정밀도에 차이가 있는 것입니다.
참고로 딥러닝에서 부동 소수점을 효율적으로 쓰자는 Mixed-Precision 라는 기법도 있습니다.
정밀한 소수 계산이 필요하면 어떡하죠?
그렇다면 정밀한 소수 값이 필요한 경우에는 어떻게 해야할까요? (우주선 발사🚀, 가상화폐 등)
해답은 Python의 decimal 라이브러리를 사용하여 고정 소수점 방식으로 정확하게 소수 연산을 처리하는 방법이 있습니다. 예시는 아래와 같습니다.
다만 고정 소수점 방식을 사용하면 메모리를 많이 사용한다는 단점이 있어 상황에 맞게 잘 사용하여야 합니다.
from decimal import Decimal
a = Decimal('0.1') + Decimal('0.1') + Decimal('0.1')
b = Decimal('0.3')
if a == b:
print("True")
else:
print("False")
# a: 0.3
# b: 0.3