모두의 dream

고정 소수점 & 부동 소수점 본문

분야/Programming

고정 소수점 & 부동 소수점

오리꽥이로 2025. 1. 13. 16:02

이진 기수법

컴퓨터에서 10진수를 저장하는 방법은 2진수이다. 

예시) 10진수 108 → 2진수 0110 1100

 

10진수가 1, 10, 100, 1000 이렇게 10^n에 해당하는 수가 될 때마다 자릿수가 올라갔다면, 2진수는 1(2) = 1(10), 10(2) = 2(10), 100(2) = 4(10), 1000(2) = 8(10) 이런식으로 2^n에 해당하는 수가 될 때마다 자릿수가 올라간다.

 

10진수를 2진수로 변환하는 방법은 다음과 같다. (2로 나눈 후 나머지 값들을 이어 2진수로 변환한다.)

그렇다면 소수를 2진수로 변환하는 방법은 무엇일까?

정수는 위 방식대로 진행하면 되지만, 소수점 아래 부분은 위 방식의 반대로 진행하면 된다.

2로 나눴던걸 2로 곱해주면 된다.

 

예시 1) 15.625

정수: 위 계산법에 따라 1111(2)

소수:

0.625 * 2 = 1.25 → 1을 빼내고 나머지 0.25

0.25 * 2 = 0.5 → 0을 빼내고 나머지 0.5

0.5 * 2 = 1.0 → 1을 빼내고 나머지 0 (0이 나오면 종료)

최종: 1111.101 (위에서부터 읽어준다.)

 

예시 2) 15.238
정수: 위 계산법에 따라 1111(2)

소수:

0.238 * 2 = 0.476 → 0 을 빼내고 나머지 

0.476 * 2 = 0.952 → 0 을 빼내고 나머지 

0.952 * 2 = 1.904 → 1 을 빼내고 나머지 

0.904 * 2 = 1.808 → 1 을 빼내고 나머지 

...

예시 2의 경우 예시 1과는 달리 깔끔하지 못한 자릿수가 늘어날 수 밖에 없는 숫자다.

따라서 10진수 소수를 2진수로 완벽하게 나타낼 수는 없다.

 

고정 소수점

위에서 소수를 2진수로 변환한 후 나온 결과값을 그대로 저장하는 방식이다.

bits 입니다! ㅎㅎ

16비트, 32비트 등 저장 공간의 크기에 따라 정수부와 소수부의 크기는 달라질 수 있으며 현재는 16비트 공간인 상황이다.

 

부호 비트: 0이면 양수, 1이면 음수.

정수는 뒤에서부터, 소수는 앞에서부터 값을 채우며 남는 자리는 0으로 채우게 된다.

 

구현은 편리하지만, 표현 가능한 범위가 적어지고 정밀도가 낮아지게 된다. 

따라서 부동 소수점이라는 방식을 대부분 사용하고 있다.

부동 소수점

부동 소수점 방식으로 표현하기 위해서는 정규화라는 과정을 거쳐야 한다.

정규화

정수부에 1만 남을 때 까지 소수점을 왼쪽(정수부가 0일 경우에는 오른쪽으로)으로 이동시키고, 이동한 칸 수 만큼 2^n으로 표시하면 되는 방식이다.

 

소수점이 오른쪽으로 가면 곱하기 2, 왼쪽으로 가면 나누기 2.

예시) 15.625(10) → 1111.101(2)

15.625 / 2  → 111.1101 (2)

31.25 / 2 → 11.11101 (2)

62.5  / 2 → 1.111101 (2)

최종: 1.111101(2) * 2^3

 

따라서 1.111101(2) * 2^3이 된다.

IEEE 754 부동소수점 표현

IEEE 754는 전기전자공학자협회(IEEE)에서 개발한 컴퓨터에서 부동소수점을 표현하는 가장 널리 쓰이는 표준이다.

부동소수점 방식으로 실수를 저장할때 32비트 또는 64비트가 사용된다.

32비트인 경우 지수부는 8bits, 가수부는 23bits이며 64비트인 경우 지수부는 10 bits, 가수부는 53 bits가 할당된다.

32비트인 경우는 단정도(Single-Precision), 64비트인 경우는 배정도(Double-Precision) 이라고 부른다.

 

부호 비트: 0이면 양수, 1이면 음수.

지수부: 정규화 후 나온 2^n에서 n에 해당하는 수를 2진수로 변환한 후 채워준다. (bias라고 하는 지정된 숫자를 더해준 값이며 IEEE 754 표준에서 32비트 bias값은 127이다. bias 값은 바뀔 수 있으므로 환경을 확인한다.)

가수부: 소수점 오른쪽에 있는 숫자들을 왼쪽부터 넣은 후 남은 자리는 0으로 채워준다. (정규화 후 소수점 왼쪽 숫자는 무조건 1이기 때문에 따로 표현하지 않는데, 이 1을 hidden bit라고 부르기도 한다.)

 

예시) 32 bits 부동소수점 방식일 경우 : 15.625(10) → (정규화 후) 1.111101(2) * 2^3

지수부: 3 + 127 = 130(10) → 10000010(2)

가수부: 1.111101(2) → 111101

 

최종 결과는 다음과 같다.

bias 값이 사용되는 이유

지수가 음수가 될 수도 있기 때문에 bias 값이 사용된다.

32비트의 bias는 127, 64비트의 bias는 1023dlek.

 

예시 1) 0.000101 (2)

정규화 진행. 정수부가 0이기 때문에 오른쪽으로 소수점을 밀어야 된다.

0.000101 * 2 = 0.00101

0.00101 * 2 = 0.0101

0.0101 * 2 = 0.101

0.101 * 2 = 1.01

 

최종: 1.01 * 2 ^ -4

 

예시 2) 0.101 (2)

0.101 *2 = 1.01

 

최종: 1.01 * 2 ^ -1

 

0 ~ 127은 음수, 128 ~ 255는 양수를 표현하도록 만들었다. 더 자세히는 0과 255는 0이나 0에 한없이 수렴하는 작은 수들, NaN(Not a Number) 같은 것들을 표현하기 위해 특별하게 지정되어 있어 일반적인 표현 범위에 포함되지 않으며, 이런 수들을 표현할 때는 이 글에서 설명한 정규화 방법이 적용되지 않는다.

10진수 소수의 2진수 변환 (오차)

따라서 컴퓨터에서 10진수를 2진수를 변환할 때 오차가 발생한다고 말하는건 소수를 부동소수점 방식으로 변환할 때 소수의 길이(예를 들면 무한소수)가 저장공간을 초과하는 경우를 말한다.

 

프로그래밍 언어에서 소수(실수)를 표현할 때 float, double 형이 사용된다.

float는 32비트, double은 64비트인데 단정도(32비트), 배정도(64비트)와 동일하다.

따라서 double형 보다 float형이 오차가 더 크다.

 

고정소수법에 비해 부동소수법은 지수로 인해 표현 가능한 숫자의 범위가 넓어져 오차를 줄일 수 있다.

Reference

https://daldalhanstory.tistory.com/147

'분야 > Programming' 카테고리의 다른 글

C언어 배열·문자열 입력  (1) 2022.01.28
컴파일 과정과 argc/argv  (0) 2022.01.10