소수(0.1같은 것)를 어떻게 표현할까?
컴퓨터가 실수를 저장하는 법에 대해 알아보자.
0. fixed point number
떠오르는 한가지 방법은 정수를 그냥 소수처럼 쓰는 것이다.
예를 들면 시간을 나타낼 때
1초는 1000밀리초니까,
0.001을 1이라고 표기하는 방식이다.
1.1 = 1.100 => 1100
25.200 => 25200
1234.567 => 1234567
이렇게 숫자를 표기하는 방식을 fixed point number라고 한다.
소수점의 위치가 항상 고정이기 때문에 fixed point라는 이름이 붙었다.
그러나 이런 방식은 큰 단점을 가진다.
사실상 정수를 표현하는 것과 다름 없기 때문에 정수형의 범위와 같은 제약을 받는다.
예를 들면, 4byte int형이 -2147483648 ~ 2147483647의 범위를 가지므로
위의 0.001 단위에서는
-2147483.648 ~ 2147483.647
밖에 표현할 수 없게 된다.
1. floating point number
따라서 다소 정확성을 잃더라도 좀 더 넓은 범위의 실수들을 저장하기 위하여 floating point, 즉, 부동 소수점이라는 방식으로 실수를 나타낼 수 있다.
다들 중학교 때 배운적이 있을 유효숫자와 지수를 이용하여 숫자를 표현한 방법을 떠올려보자.
1234 = 1.234 * 10^3
0.065 = 6.5 * 10^(-2)
이 방법을 이용하여 실수를 표현한다면 0번의 고정 소수점보다 더 크거나 작은 수들을 표현할 수 있을 것이다.
이 방법으로 실수를 표현하기 위해서는
부호
지수
유효숫자
를 나타낼 필요가 있다.
이 모든 비트들을 합쳐서 8비트에 저장한다고 하면
부호 - 지수 - 유효숫자
1비트 - 3비트 - 4비트
정도로 나타낼 수 있을 것이다
그럼 이제 각 부분이 어떻게 구성되는 지를 알아보자.
<부호>
실수의 부호에는 음과 양이 있다.
양수는 0
음수는 1
<지수>
지수는 몇개를 표현할 수 있을까?
3비트니까 일단 8가지의 지수를 표현해야할 것이다.
그런데 지수비트들이 000인 (모두 0인) 것은 절대값이 작은 소수들을 위해 예약되어있다.
(111 또한 무한대 혹은 NaN - 후에 설명- 을 위해 예약되어 있다.)
따라서 001부터 110까지 7가지를 지수들을 표현하는 데에 쓸 것인데,
지수에는 양수뿐만 아니라 음수도 존재하기 때문에
음의 지수 3개, 양의 지수 3개를 표현하게 된다.
그러나 이 부분을 일반적인 정수형의 음수를 사용하지 않고
bias라는 것을 사용하여 지수를 표현한다.
bias는 다음과 같이 정해진다.
2^(b-1)-1
(b가 지수비트의 길이일 때)
우리의 예시에서는 지수비트가 3비트이므로
2^(3-1)-1 = 3
지수파트의 비트들에 bias를 뺀 값이 실제 지수이다.
무슨 말이냐 하면, 6-3 = 3
1-3 = -2
-2부터 3까지의 지수를 표현할 수 있다는 의미이다.
<유효숫자>
유효숫자 부분은 쉽다.
그냥 유효숫자를 생각하면 된다.
다만 2진수의 실수에서 유효숫자의 첫자리(정수자리)는 반드시 1이 되므로 1은 생략하고 소수부분만 적는다.
예를 들어
십진수로 1.5는 1+1/2 이므로
1.100000
앞에 1.을 떼고 유효숫자가 4비트이므로
1000
으로 저장된다.
이제 실제 숫자를 저 형태로 만들어보자.
3.5를 생각해보자.
먼저 2진수로 바꾸는 작업을 하자.
3.5 = 1.75 * 2 = (1+1/2+1/4) * 2
1.110 * 2^1
부호 : 양수이므로 0
지수 : x-3 = 1이므로 x = 4 = 100(2)
유효숫자 : 1.1100에서 1100만 딴다
종합하면
0 100 1100이 3.5가 되는 것이다.
다음은 좀 더 현실적인 예시이다.
파이의 값을 근사하였다.
2. 범위
아까 처음에 봤던 고정 소수점 방식에서 4바이트인 int형을 사용한 소수표현 방식은
10진수로 유효숫자가 9.2자리정도 (첫자리는 1,2만 가능하므로)
소수점은 9칸부터 1칸까지 표현할 수 있다.
그렇다면 같은 4바이트에서 실수형은 얼마나 많은 수들을 표현할 수 있을까?
4바이트 = 32비트에서 각 비트들은
부호 - 지수 - 유효숫자 순으로
1비트, 8비트, 23비트를 차지한다.