# 컴퓨터가 소수점을 저장하는 방식: IEEE‑754부터 금융용 Decimal까지 완전 정복

*SEO 키워드: 컴퓨터, 소수점 저장, IEEE‑754*

---

# # 📌 서론 – “왜 컴퓨터는 0.1을 정확히 표현하지 못할까?”

우리는 일상에서 **0.1**, **0.25**, **3.14159** 같은 소수점을 자유롭게 사용합니다. 하지만 프로그래밍을 할 때 “`0.1 + 0.2`가 `0.3`이 아니다”는 오류를 마주하면 당황하곤 하죠.

이 현상의 근본 원인은 **컴퓨터가 소수를 이진수(0과 1) 형태로만 저장한다**는 점에 있습니다.

본 글에서는

1. **IEEE‑754 부동소수점**이 어떻게 동작하는지,

2. **왜 정확히 표현되지 않는가**에 대한 원리,

3. **금융·회계에 특화된 Decimal 타입**이 어떻게 문제를 해결하는지

를 차근차근 풀어 설명합니다. 초보자도 이해할 수 있도록 그림과 예시를 풍부하게 넣었으니, 끝까지 읽고 직접 실습해 보세요!

---

# # 1️⃣ IEEE‑754 부동소수점 – 컴퓨터의 기본 소수 저장 방식

## # 1-1. 구조 살펴보기

IEEE‑754는 **부동소수점(Floating‑Point)** 표준으로, 현재 대부분의 프로그래밍 언어와 하드웨어가 따릅니다. 가장 흔한 **double(64비트)** 형식은 다음과 같이 구성됩니다.

| 비트 | 의미 | 비고 |

|------|------|------|

| 1    | 부호 비트 (Sign) | 0 = 양수, 1 = 음수 |

| 11   | 지수 (Exponent) | 바이어스(1023) 적용 |

| 52   | 가수 (Mantissa) | 숨겨진 1을 포함한 정밀도 15~17자리 |

> **예시**: `0.15625` 를 IEEE‑754 double 로 변환하면

> - 부호 = 0

> - 지수 = 1023‑4 = 1019 (binary `01111111101`)

> - 가수 = `010100000000…`

## # 1-2. 왜 0.1은 정확히 표현되지 않을까?

10진수 `0.1` 은 이진수로 **무한히 반복되는** 소수입니다.

```

0.1 (10진) = 0.000110011001100… (2진)   // 무한 반복

```

IEEE‑754는 **52비트 가수**만 저장하므로, 무한히 이어지는 비트를 잘라 버립니다. 그 결과 실제 저장값은 `0.10000000000000000555…` 가 되며, 연산 시 오차가 누적됩니다.

## # 1-3. 부동소수점 연산에서 흔히 보는 오류 사례

| 코드 (Python) | 기대값 | 실제값 |

|---------------|--------|--------|

| `0.1 + 0.2`   | `0.3`  | `0.30000000000000004` |

| `1.0/3.0`     | `0.333…`| `0.3333333333333333` |

오차는 **작지만** 금융·과학 계산에서는 치명적일 수 있습니다.

---

# # 2️⃣ Decimal 타입 – 금융·회계에 최적화된 정확한 소수

## # 2-1. Decimal이란?

Decimal(또는 **BCD(Binary‑Coded Decimal)**)은 **10진수 자리마다 4비트**를 할당해 **10진수를 그대로 저장**합니다. 대표적인 구현은

- **C#** `decimal` (128비트, 28~29자리 정확도)

- **Java** `java.math.BigDecimal`

- **Python** `decimal.Decimal`

## # 2-2. Decimal의 내부 구조

| 비트 | 의미 |

|------|------|

| 1    | 부호 |

| 96   | 10진수 정수 부분 (3×32비트) |

| 8    | 스케일(소수점 이하 자리수, 0~28) |

| 23   | 예약 비트(0) |

예를 들어 `123.45` 를 저장하면

- 정수 부분 = `12345`

- 스케일 = `2` (소수점 이하 2자리)

이렇게 하면 **오차 없이 정확히** 표현할 수 있습니다.

## # 2-3. 언제 Decimal을 사용해야 할까?

| 상황 | 권장 타입 |

|------|-----------|

| 은행·회계 시스템 (이자, 세금) | Decimal / BigDecimal |

| 과학·공학 시뮬레이션 (대규모 연산) | IEEE‑754 double |

| 그래픽·게임 물리 엔진 | IEEE‑754 float (단일 정밀도) |

특히 **법적·재무 보고**에서는 “소수점 오차가 0.01원이라도 안 된다”는 규정이 있기 때문에 Decimal이 필수입니다.

---

# # 3️⃣ 실전 팁 – 부동소수점과 Decimal을 현명하게 선택하기

1. **오차 허용 범위 정의**

   - `Math.abs(a - b) < 1e-9` 와 같이 허용 오차를 명시하면 부동소수점 오류를 감출 수 있습니다.

2. **연산 순서 최적화**

   - 큰 수와 작은 수를 더할 때 작은 수가 소멸될 위험이 있으니, **작은 수부터 더하기**가 안전합니다.

3. **Decimal 변환 비용 고려**

   - Decimal은 메모리와 연산 속도가 부동소수점보다 무겁습니다.

   - **핵심 로직**은 double로 빠르게 처리하고, **결과 출력·저장** 단계에서 Decimal로 변환하는 전략을 쓰세요.

4. **라이브러리 활용**

   - Python: `from decimal import Decimal, getcontext` → `getcontext().prec = 28`

   - Java: `BigDecimal.valueOf(0.1).add(BigDecimal.valueOf(0.2))`

---

# # 4️⃣ 결론 – 올바른 소수 저장으로 신뢰성을 높이자

컴퓨터는 **이진수** 기반이기 때문에 10진 소수를 완벽히 표현하지 못합니다. 하지만 **IEEE‑754**는 일반적인 과학·공학 계산에 충분히 빠르고 효율적인 반면, **Decimal**은 금융·회계처럼 정확도가 생명인 분야에 최적화돼 있습니다.

> **핵심 포인트**

> - 부동소수점은 **정밀도 손실**이 발생한다 → 오차 허용 범위와 연산 순서에 주의.

> - Decimal은 **정확한 10진 표현**을 제공 → 비용을 감수하고 사용해야 하는 상황을 명확히 구분.

## # 📣 행동 유도

1️⃣ 오늘 작성 중인 **재무·회계 코드**가 있다면, `float`/`double` 대신 **Decimal**(또는 `BigDecimal`)로 교체해 보세요.

2️⃣ **연산 테스트**를 직접 해보세요.

```
python

from decimal import Decimal

print(Decimal('0.1') + Decimal('0.2'))   # 0.3 정확히 출력

```

3️⃣ 블로그 댓글에 **당신이 겪은 소수점 오류 사례**를 공유하면, 함께 해결책을 찾아볼 수 있습니다!

---

*이 글이 도움이 되었다면, SNS·카카오톡으로 공유하고, 다음 포스트에서는 “부동소수점 연산 최적화 팁”을 다룰 예정이니 구독과 알림 설정도 잊지 마세요!*
