owel의 블로그

컴퓨터는 실수를 어떻게 저장할까? 고정소수점 vs 부동소수점

태그:
  • CS
image

컴퓨터는 데이터를 이진수 체계를 이용해 0과 1로 저장합니다.
정수를 저장할 경우 해당 정수를 이진수로 변환한 후 메모리에 저장하는데, 우측부터 2⁰, 2¹, 2²... 순으로 해석하여 변환합니다.

그런데 125.27525.23423112342343... 같이 소수부가 포함된 실수는 어떻게 저장할까요?

두 실수 사이에는 무수히 많은 실수가 존재한다는 특성상, 이를 유한한 비트로 나타내려면 정수의 변환과는 다른 복잡한 규칙이 필요합니다.
이를 위해 개발된 대표적인 두 가지 방법인 고정소수점(Fixed-point)부동소수점(Floating-point) 방식을 살펴보겠습니다.

고정소수점 방식 (Fixed-point)

고정소수점 방식은 실수를 이진수로 변환할 때 정수 부분과 소수 부분을 각각 별도의 정수처럼 저장하는 방식입니다.

부동소수점 방식보다 먼저 사용되던 방식으로, 부동소수점이 등장한 이후 두 방식을 구분하기 위해 "고정소수점"이라 부르게 되었습니다.

아래 설명은 널리 사용되는 Q8.8 형식 (정수부 8비트 + 소수부 8비트, 총 16비트) 을 기준으로 합니다.

변환 과정

1단계) 정수부와 소수부를 각각 이진수로 변환

125.625

  • 정수부 12501111101
  • 소수부 0.62510100000

2단계) 두 이진수를 결합하여 16비트로 저장

01111101 10100000
└─정수부─┘└─소수부─┘

장점

  • 정확한 표현: 소수 부분을 정수처럼 저장하기 때문에 지정된 크기 내에서는 정확한 값을 유지할 수 있습니다.
  • 구현 간단: 정수의 저장 방식과 연산 방식을 그대로 사용하므로 직관적이고 구현하기 쉽습니다.

단점

  • 유연성 부족: 정수부와 소수부의 저장 공간 크기를 미리 결정해야 하므로, , 정해진 크기보다 작은 수가 들어온다면 저장공간이 낭비되고, 정해진 크기보다 큰 수가 들어온다면 값이 넘쳐 손실이 일어나는 등 예외적인 값들에 대한 효율적 대응이 어렵기에 초기에 저장 공간의 크기를 잘 설정해야 합니다.
  • 하드웨어 미지원: 과거에는 연산 시 정수의 연산 체계를 그대로 사용하기에 빠른 연산 속도가 장점이었지만, 현대 CPU에는 대부분 부동 소수점 연산을 빠르게 처리하는 FPU(Floating Point Unit)가 내장되어 있어 상대적으로 고정 소수점 방식이 느려졌습니다.

부동소수점 방식 (Floating-point)

부동소수점 방식은 실수를 sign(부호비트), exponent(지수부), fraction(가수부) 의 세 가지 구성 요소로 나누어 저장합니다.

아래 설명은 널리 사용되는 IEEE 754 단정밀도(32비트) 표준을 기준으로 합니다.

32비트 구성

image
구성 요소 비트 수 역할
sign (부호비트) 1비트 양수(0) / 음수(1)
exponent (지수부) 8비트 소수점 위치 표현 (bias 127 적용)
fraction (가수부) 23비트 정규화된 실수 값 저장
  • 지수부는 0~255 저장 가능하며, 0과 255는 특수값 예약
  • 실제 지수 표현 범위: -126 ~ 127 (저장 시 127을 더해 1~254로 저장 → 이 127을 bias라 함)

💡 bias란?

지수부는 8비트 부호 없는 정수(0~255)로 저장됩니다. 그런데 실제 지수 값은 음수도 될 수 있습니다 (예: 0.001을 정규화하면 1.0 × 2⁻³). 부호 없는 정수로 음수 지수를 표현하기 위해 실제 지수 값에 127을 더한 값을 저장하는 방식을 사용하는데, 이 더해주는 값 127을 bias 라고 합니다.

실제 지수 저장되는 값 (지수 + 127)
-126 1
0 127
6 133
127 254

이렇게 하면 별도의 부호 비트 없이도 지수부만으로 음수 지수를 표현할 수 있고, 저장된 값이 클수록 실제 지수도 크다는 대소 관계가 유지되어 부동소수점 수의 크기 비교도 간단해집니다.

변환 과정 (-125.625 예시)

1단계) 부호 비트 저장

양수일경우 0 을, 음수일경우 1 을 저장합니다.

여기서는 음수이므로 1 을 저장합니다.

1 | ???????? | ???????????????????????

2단계) 이진수 변환

  • 정수부 1251111101
  • 소수부 0.625.101
  • 결합: 1111101.101

3단계) 정규화 및 가수부 저장

소수점을 맨 앞 1 다음으로 이동:

1111101.101  →  1.111101101 × 2⁶

이후, 맨 앞 1을 제외한 나머지 111101101를 가수부에 저장합니다.
이 맨 앞의 1은 정규화 과정에서 항상 존재하는 것이 보장되는 값으로(맨 앞 1 다음으로 소수점을 옮기기에) 암묵적으로 간주되므로 저장할 필요가 없습니다(이를 "hidden bit"라고 함).
가수부의 제일 왼쪽부터 111101101을 채우고, 나머지 빈 공간은 0으로 채웁니다.

1 | ???????? | 11110110100000000000000

4단계) 지수부 저장

소수점 이동 자릿수 6 + bias 127 = 133 → 이진수 10000101

1 | 10000101 | 11110110100000000000000

장점

  • 넓은 표현 범위: 같은 비트 수로 고정 소수점 방식보다 훨씬 넓은 범위의 숫자를 표현할 수 있습니다. 실수 전체를 이진수로 변환하여 가수부에 저장한 후, 소수점의 위치를 지수부에 저장하기 때문에 소수점의 위치를 유연하게 지정할 수 있습니다.(부동 = 소수점이 둥둥 떠다님) 그렇기에 정수와 소수 각각의 저장에 사용되는 비트를 고정할 필요가 없으므로, 가수부의 공간에 정수가 작을 경우 소수 저장에 더 많은 비트를 사용할 수 있고, 소수가 작을 경우 정수 저장에 더 많은 비트를 사용할 수 있기에 고정소수점 방식에 비해 저장 공간을 효율적으로 사용할 수 있습니다.
  • 하드웨어 지원: 현대 CPU에는 부동소수점 연산을 빠르게 처리하는 전용 회로(FPU, Floating Point Unit)가 내장되어 있어 빠른 연산이 가능합니다.

단점

  • 정밀도 손실: 일부 실수(예: 0.2, 0.3)는 이진 부동소수점으로 정확히 표현할 수 없어(0.2는 이진수로 0.00110011001100... 같이 무한히 반복되는 형태가 됨) 근삿값으로 저장됩니다.
  • 오차 누적: 부동소수점 수를 이용해 반복적인 연산을 하는 과정에서 작은 오차가 누적되면 계산 결과가 부정확해질 확률이 높아집니다.
  • 특수값 처리: NaN, 무한대 등 특별한 값을 처리하기 위한 추가 로직이 필요합니다.

각 방식의 적합한 사용 사례

방식 적합한 분야 이유
고정소수점 금융, 회계, 암호화폐 거래소 미세한 오차조차 허용되지 않는 정확한 금액 계산 필요
부동소수점 물리 시뮬레이션, 날씨 예측, 3D 그래픽, 머신러닝 넓은 숫자 범위를 빠르게 처리해야 하며, 작은 오차는 허용 가능

정리

실수 표현 방식
├── 고정소수점: 정확도 ↑, 표현 범위 ↓, 구현 간단
└── 부동소수점: 표현 범위 ↑, 정확도 ↓ (근삿값), 하드웨어 가속 지원

두 방식 모두 장단점이 명확하기 때문에, 어떤 정밀도와 범위가 필요한지에 따라 적절한 방식을 선택하는 것이 중요합니다.