실수의 내부 표현

컴퓨터에서 실수를 표현하기 위해서는 2진수 기반의 메모리 비트로 표현해야 합니다.
정수부는 기존의 2진수 정수 변환 방식과 동일하며, 소수부는 아래와 같은 방식으로 2진수로 변환됩니다.

actual number.png

10진수 소수를 2진수로 변환하는 절차는 다음과 같습니다.

  1. 절대값이 1보다 작은 소수에 2를 곱합니다.
  2. 곱셈 결과의 정수 부분이 1이면 1, 0이면 0을 2진수 자릿수로 기록합니다.
  3. 소수 부분이 0이 될 때까지 반복합니다. (무한 반복될 수 있습니다.)

예를 들어, 10진수 $0.75, 0.65625$의 경우 각각 2진수 $0.11, 0.10101$이라는 결과가 나옵니다.

이렇게 변환한 2진 소수를 컴퓨터 메모리에 저장하는 방식은 크게 두 가지가 있습니다.
고정 소수점(Fixed Point) 방식과 부동 소수점 (Floating Point) 방식입니다.

고정 소수점 표현 방식

고정 소수점(Fixed Point)은 정수 부분을 표현하는 비트 수와 소수를 표현하는 비트 수를 사전에 정한 후 해당 비트 수만을 이용하여 수를 표현하는 방식입니다.
즉, 정수부와 소수부의 비트 수를 미리 고정해서 사용하는 방식입니다.

고정 소수점은 소수부의 자릿수를 미리 정하고 고정된 자릿수의 소수를 표현하기 때문에 직관적입니다.

32비트 고정 소수점을 다음과 같이 사전에 정한 경우를 예로 들어보겠습니다.

FixedPoint

  • 처음 1비트는 부호를 나타냅니다. 양수는 0 음수는 1입니다.
  • 다음 15비트는 정수부를 나타냅니다.
  • 다음 16비트는 소수부를 나타냅니다.

이렇게 구성한다면, 소수부는 정확히 $2^{-1}$ ~ $2^{-16}$까지 표현할 수 있습니다.

10진수 $5.75$를 2진수로 변환하고, 32비트 고정 소수점으로 표현해보면 다음과 같습니다.

FixedPoint_ex

10진수 $0.1$을 2진수로 변환하면 $0.1_{(10)} = 0.00011001100110011 \ldots _{(2)} (무한 반복)$ 로 무한하게 반복합니다.
하지만 고정 소수점에서는 소수부 비트 수가 제한되어 있기 때문에 만약 소수부가 8비트라면 $0.00011001$와 같이 뒷 부분이 잘리게 됩니다.
이 경우 다시 10진수로 변환하면 $0.046875$가 저장됩니다.

고정 소수점의 장단점

고정 소수점 표현 방식의 장점은 다음 두 가지로 요약할 수 있습니다.

첫째, 연산 효율성이 높습니다.
고정 소수점 방식은 실수를 정수 기반으로 변환하여 처리하므로, 실수형 연산보다 연산 회로가 단순하고 빠릅니다.
특히 곱셈 및 나눗셈 같은 연산에서도 부동 소수점보다 적은 연산량과 메모리를 요구하여, 연산 자원이 제한된 환경에서 효과적입니다.

둘째, 표현에 필요한 비트 수가 적습니다.
고정 소수점 방식은 사전에 정해진 비트 수만으로 수를 표현하기 때문에, 메모리 사용량이 작고 데이터 전송 효율이 높습니다.
특히 임베디드 시스템, DSP, 대규모 행렬 연산을 수행하는 경우, 8비트 또는 16비트 고정 소수점 형식을 사용하면 전체 연산량과 메모리 사용을 크게 줄일 수 있습니다.

단점은 표현 가능한 수의 범위와 정밀도 사이에 트레이드오프(상충 관계)가 있다는 것입니다.
고정된 전체 비트 수 내에서 정수부의 비트를 늘리면 더 큰 수를 표현할 수 있지만, 소수부의 정밀도는 떨어집니다.
반대로 소수부의 비트를 늘리면 더 정밀한 수를 표현할 수 있으나 표현 가능한 정수 범위가 좁아집니다.
이로 인해 실수의 근사 오차가 발생할 수 있으며, 누적 연산에서는 오차가 커질 수 있습니다.

부동 소수점 표현 방식

부동 소수점(Floationg Point)의 부동(浮動)은 일반적으로 알려진 ‘움직이지 않음’ 뜻의 부동(不動)이 아니라, ‘떠서 움직이는’이라는 의미입니다.
이는 소수점의 위치가 수의 크기에 따라 자유롭게 이동(floating)할 수 있다는 특성에서 유래한 용어입니다.

부동 소수점 표현 방식은 고정 소수점과는 다른 비트 구성 체계를 사용하며, 그중 가장 널리 쓰이는 방식은 전기전자기술자협회(IEEE)에서 제안한 IEEE 754 표준입니다.

FloationgPoint

  1. 2진수 정규화(normalize)
    • 실수를 2진수로 변환한 후, 소수점을 맨 앞의 1 뒤로 이동시켜 $1.*** \times 2^n$의 형태로 만듭니다.
  2. 부호 비트(Sign bit)
    • 총 1비트로, 값이 양수면 0, 음수면 1로 설정됩니다.
  3. 지수부(Exponent)
    • 정규화한 결과의 지수를 바이어스 값(127)과 더해 8비트로 저장합니다.
  4. 가수부(Mantissa)
    • 정규화한 이진수 표현에서 소수점 뒤의 부분만을 따로 저장합니다.

10진수 $5.75$를 2진수로 변환하고, 32비트 부동 소수점으로 표현해보면 다음과 같습니다.

FloationgPoint_ex

정규화

여기서 정규화(Normalization)란 2진수 실수를 $1.\textrm{xxx} \times 2^n$ 형태로 변환하는 과정을 말합니다.
즉, 소수점을 이동시켜 가장 왼쪽에 1이 오도록 만드는 과정이며, 이를 통해 실수 값을 표준화된 형태로 표현할 수 있습니다.

예를 들어, 10진수 $5.75$를 2진수로 바꾸면 $101.11_{(2)}$입니다.
이 값을 정규화하면 $1.0111_{(2)} \times 2^2$로 나타낼 수 있으며, 이때 지수(exponent)는 $2$가 됩니다.

지수부

지수부(Exponent)는 정규화에서 얻은 지수 값을 그대로 저장하지 않고, IEEE 754 표준에 따라 바이어스(bias) 값을 더한 값으로 저장합니다.

32비트 부동 소수점 표현에서 지수부는 8비트로 구성되며, 총 256개의 값을 표현할 수 있습니다.

32비트 부동 소수점 표현에서는 바이어스 값으로 $127$이 사용됩니다.
예를 들어 지수가 $2$일 경우 실제 저장되는 값은 $2 + 127 = 129$가 됩니다.
이 값을 2진수로 바꾸면 $10000001_{(2)}$로 표현됩니다.

바이어스 값을 사용하는 이유는 지수가 음수인 경우를 표현하기 위해서입니다.
지수에 부호 비트를 따로 두는 대신, 모든 지수를 양의 정수로 바꾸기 위해 바이어스를 더하는 방식을 사용합니다.

예를 들어, $0.0101_{(2)}$를 정규화하면 $1.01_{(2)} \times 2^{-2}$가 되는데, 이 경우 지수는 $-2$이므로 바이어스 127을 더해 $-2 + 127 = 125$를 저장합니다.
즉, 지수부에 $01111101_{(2)}$가 기록됩니다.

32비트 부동 소수점 표현의 경우 실제 지수의 값과 저장되는 값은 다음과 같습니다.

실제 지수 값 저장되는 값 (10진수) 저장되는 값 (2진수)
$-126$ $1$ 00000001
$0$ $127$ 01111111
$+127$ $254$ 11111110

0000000011111111은 각각 0, 무한대 혹은 NaN을 표현하기 위해 예약된 값입니다.

가수부

가수부(Mantissa)는 정규화된 2진수의 소수 부분을 저장하는 영역입니다.
정규화된 수의 정수 부분은 항상 1이기 때문에 저장하지 않으며, 소수 부분만을 맨 앞에서부터 23비트까지 저장합니다.

예를 들어, 정규화 결과가 $1.0111_{(2)}$라면, 저장되는 가수부는 01110000000000000000000입니다.

이러한 저장 방식은 가장 앞자리가 1이라는 것을 항상 가정한다는 전제에 기반합니다.
따라서 한 비트를 절약할 수 있어 더 효율적인 표현이 가능합니다.

부동 소수점의 장단점

장점으로는 다음과 같습니다.
부동 소수점은 고정 소수점에 비해서 더 큰 수의 범위를 표현 할 수 있습니다.

단점으로는 다음과 같습니다.
부동 소수점 자료형 처리는 고정소수점 자료형 처리에 비해 복잡한 연산이 필요하므로 컴퓨터 하드웨어의 성능을 표현할 때 부동 소수점 처리 능력이 빠지지 않습니다.
실수 연산이 부정확할 수 있다는 것이 가장 큰 단점입니다. 이는 컴퓨터 하드웨어가 가지는 본질적인 한계점 때문에 완벽하게 극복할 수는 없습니다.

소수 계산 오차

하지만 모든 10진수가 2진수로 깔끔하게 떨어지지는 않습니다.
예를 들어 0.2라는 값을 2진수로 변환한다면 $0.001100110011 \ldots$로, 특정 비트 패턴이 무한히 반복되는 순환소수가 됩니다.

부동 소수점이 아무리 큰 수를 표현할 수 있다고 해도 메모리에는 한계가 있습니다.
따라서 무한히 반복되는 소수를 모두 저장할 수 없고, 정해진 비트 내에서 표현 가능한 근사값(approximation)으로 저장됩니다.

근사값으로 어떻게 표현을 할 것인지에 대한 기준으로 IEEE 754에서 정의한 방법은 다음과 같습니다.

  • 가장 가까운 수로 반올림 (Round to nearest)
  • 올림 (Round up, round toward plus infinity)
  • 내림 (Round down, round toward minus infinity)
  • 0으로 절삭 (Round toward zero, chop, truncate)

가장 가까운 수로 반올림

가장 일반적으로 사용되는 반올림 방식입니다.
가장 가까운 수로 반올림하며, 정확히 두 값의 중간일 경우 짝수 방향으로 반올림합니다.

절반을 자리올림하고, 나머지 절반은 자리내림 합니다. 즉 반올림을 하는 것이라고 생각하면 됩니다.

결과 값이 정확히 두 값의 가운데 위치할 때 최하위 비트가 홀수이면 더하기1, 짝수이면 잘라내는 것입니다.
이 방법은 항상 최하위 비트를 0으로 만들어줍니다.

예시는 다음과 같습니다.

  • $2.3 \rightarrow 2$
  • $2.5 \rightarrow 2$ (짝수 방향)
  • $2.7 \rightarrow 3$
  • $3.5 \rightarrow 4$ (짝수 방향)
  • $-2.3 \rightarrow -2$
  • $-2.5 \rightarrow -2$ (짝수 방향)
  • $-2.7 \rightarrow -3$
  • $-3.5 \rightarrow -4$ (짝수 방향)

올림

항상 무한대 방향(양수 방향)으로 변경합니다.
즉, 양수인 경우 0에서 먼 값, 음수인 경우 0에 가까운 값으로 변경합니다.

예시는 다음과 같습니다.

  • $2.3 \rightarrow 3$
  • $2.5 \rightarrow 3$
  • $2.7 \rightarrow 3$
  • $-2.3 \rightarrow -2$
  • $-2.5 \rightarrow -2$

내림

항상 음의 무한대 방향(음수 방향)으로 변경합니다. 즉, 양수인 경우 0에 가까운 값, 음수인 경우 0에 먼 값으로 변경합니다.

예시는 다음과 같습니다.

  • $2.3 \rightarrow 2$
  • $2.5 \rightarrow 2$
  • $2.7 \rightarrow 2$
  • $-2.3 \rightarrow -3$
  • $-2.5 \rightarrow -3$

0으로 반올림하거나 절삭

항상 0에 가까운 방향으로 소수점을 절삭합니다.
즉, 소수점 이하를 잘라내는(truncate) 방식입니다.

예시는 다음과 같습니다.

  • $2.5 \rightarrow 2$
  • $3.9 \rightarrow 3$
  • $-3.9 \rightarrow 3$

단정도와 배정도

단정도(Single Precision)와 배정도(Double Precision)는 부동 소수점 방식에서 실수를 표현할 때 사용하는 포맷입니다.
IEEE 754 표준에서 사용되며, 각각 비트 수, 표현 가능한 정밀도 및 범위에서 차이가 있습니다.

구분 단정도 배정도
비트 수 32비트 64비트
부호 비트 1비트 1비트
지수 비트 8비트 11비트
가수 비트 23비트 52비트
바이어스 값 127 1023
정밀도 약 7자리 약 15~16자리
표현 범위 $\pm 10^{-38} ~ \pm 10^{38}$ $\pm 10^{-308} ~ \pm 10^{308}$

메모리 사용이 제한적이고, 정밀도보다 속도가 중요한 경우 단정도인 float를 사용합니다.
고정밀 계산이 필요한 과학, 공학, 금융 분야 등에서 배정도인 double을 사용합니다.

참조

arm IEEE 754 arithmetic and rounding
arkainoh [C/C++] 고정 소수점의 모든 것 (All about Fixed Point)
Gukwon Koo CS50 - 고정 소수점(fixed point)과 부동 소수점(floating point)
등 긁는 봉황대 [Chapter 3. 컴퓨터 연산] IEEE 754 부동소수점 반올림과 근사

ComputerScience 카테고리 내 다른 글 보러가기

댓글남기기