컴퓨터 연산에서는 소수를 어떻게 처리할까?
고정 소수점은 소수를 정수부와 소수부로 표현하는 데이터 형식이다.
예를 들어 32.495 라는 소수가 있으면, 정수부 32와 소수부 .495 로 나누어 표현하는 것이다.
고정 소수점 방식으로 저장한다는 것은, 소수부를 각 자리마다 따로 저장한다는 것이다.
즉, 소수부의 4 = 100, 9 = 1001, 5 = 101 로 변환되어 저장되기 때문에, 소수부 한 자리마다 최대 4 bit가 필요하게 된다.
소수점 아래 자릿 수가 1-2개 정도로 적다면 크게 문제가 되지 않지만, 자릿 수가 많다면 메모리가 감당할 수 없게 된다.
이러한 문제점을 보완하고자 부동 소수점 형식이 고안되었다.
여기서 부동은 不動 (not moving) 이 아니라 浮動 (floating), 즉 떠 다닌다는 의미이다.
우선 소수를 정규화하여 (소수점을 옮긴다 → 소수점이 浮動 (floating)) 가수부와 지수부로 나눈다.
32.495 = 3.2495 (가수부) × 10 (지수부)
부동 소수점을 이용하면 고정 소수점 방식을 사용했을 때보다 넓은 범위의 수를 나타낼 수 있고 메모리도 효율적으로 사용할 수 있게 된다.
파이썬에서 print(0.1+0.2)를 해보자. 0.3이 나올 것으로 기대하겠지만, 실제로는 0.30000000000000004라는 결과가 나온다. 왜 이런 것일까?
컴퓨터에서는 실수를 2진수로 변환해서 저장하는데, 일부 소수는 2진수로 정확하게 표현할 수 없다. 0.1과 0.2가 대표적인 예시이다. 0.1을 2진수로 표시하면 = 와 같이 0011이 무한히 반복되는 무한 소수가 되어서, 컴퓨터에서는 적절한 자리에서 반올림해서 근사값으로 저장하게 된다. 따라서 0.1 + 0.2의 연산이 0.3이 되는 것이 아니라 0.30000000000000004처럼 미세한 오차가 생기게 된다.
보다 정확한 결과를 얻고 싶다면 decimal 모듈을 이용하자.
from decimal import Decimal
print(Decimal('0.1') + Decimal('0.2')) # 0.3
* 파이썬에서만 발생하는 문제가 아니라 C, Java 등 대부분의 프로그래밍 언어에서 같은 결과가 나온다.