About floating point(부동소수점)

Updated:

부동소수점은 컴퓨터가 소수(ex 12.88)를 표현하는 방식이다.

그 방법은 다음과 같다.

  1. 소수를 2진수로 표현.
  2. 부호 비트(1bit), 지수부(8bits), 가수부(23bits)로 구분.
  3. 각 파트 별로 변환

변환사이트


1. 소수 -> 2진수

우선 소수를 2진수로 표현해보자. 일반적으로 사용하는 소수는 정수부와 실수부로 구분된다. 정수부의 2진수 변환은 잘 알려져 있기 때문에 생략하고, 소수부의 2진 변환은 어떻게 하는걸까?

  • 소수점을 2진수로 나타내는법

Ex) 0.625

  1. 2를 곱한다 0.625 * 2 = 1.25 (1은 소수자리로, 나머지 0.25는 다시 연산) 나온 소수점 1
  2. 정수부를 소수점 첫째자리로.
  3. 정수부를 제거한 뒤 위 과정을 반복한다.s

0.25 * 2 = 0.5 (0은 소수자리로, 나머지 0.5는 다시 연산) -> 나온 소수점 10
0.5 * 2 = 1.0 (1은 소수자리로, 나머지 0.0이므로 종료)-> 소수점 : 101


2. Sign, Exponent, Mantissa

부동소수점으로 표현된 소수는 세 부분으로 나뉘게 된다.

10.25를 예로 들어 설명해보자.

- Sign bit
부호를 나타내는 하나의 비트로 1은 음수를, 0은 양수를 의미한다. MSB(Most Significant Bit)에 위치한다(가장 왼쪽 비트)

10.25는 양수이므로 sign bit는 0이 된다.


- Exponent
지수를 나타내는 8개의 비트이다. 예를들어 10.25는 이진수로 표현하면 1010.01 인데 지수부를 나타낼때는 1.01001 * 2^3 과 같이 표현한다. 즉 정수 부분을 한자리로 표현하고 나머지를 소수부분에 몰아넣게 된다. 만약 이진수 변환된 소수가 0.1010일 경우 변환하면 1.010 * 2^-1이 된다 (왼쪽으로 옮겨야 하므로).

변환된 10.25는 1.01001 * 2^3이라는 것 까지 구했다. 이 때 지수부는 2의 지수를 뜻하게 되며 여기서는 3이 된다. 그럼 8비트 표현하면 0000_0011인가?

정답은 1000_0010이다. 지수부에서 0은 0111_1111로 표현된다. 그 이유는 아래에 따로 기재하였다.


- Mantissa
가수부는 나머지 23비트에 해당되는 부분으로, 위에서 변환한 1.01001 * 2^3에서 소수점 아래 부분에 해당된다. 즉 01001이 가수부에 해당되며 23비트 만큼 뒤에 0으로 채워주면 된다.

따라서 10.25의 부동소수점 표현은 아래와 같다.
0100_0001_0010_0100_0000_0000_0000_0000


왜 부동소수점을 사용할까?

만약 단순히 31비트를(부호비트 제외) 정수부와 소수부로 나누면 무엇이 문제일까?

표현가능한 스케일의 trade-off가 발생한다 생각한다. 정수부를 표현하는 비트가 많아질수록 표현가능한 범위는 넓어지겠지만 그만큼 소수부가 줄어들기 때문에 정밀한 표현은 불가능하다. 그 반대로 소수부의 비트가 증가하면 세밀한 수의 표현은 가능하나 정수부 비트가 줄어들기 때문에 표현 가능한 수의 범위는 줄어들게 된다. 사용자마다 필요한 입맛에 맞추어 정수부와 소수부의 크기를 조정할 수는 있겠지만 그렇게 된다면 다르게 정의된 프로그램끼리는 충돌이 일어날 것이다.


지수부에 Bias (127)을 더하는 이유는?

32비트 부동소수점 방식에서 지수부는 8비트를 차지한다. 단순히 생각하면 0000 0000 = 0 이라고 생각할 수 있는데 사실 0은 0111 1111로 표현된다 (IEEE 754 standard). 즉 bias = 127를 더해준 표현을 사용하는데 왜그런지 생각해보자.

지수부는 2^x에서 x를 표현하게 된다. 이때 지수는 음의 값, 양의 값 모두 가질 수 있다 (8비트이므로 -127 ~ 128). 하지만 지수부는 sign bit가 정의되지 않기 때문에 127만큼의 bias를 더해줘서 지수부를 따로 설정하지 않고

0000 0000 = -127
1111 1111 = 128

이렇게 표현할 수 있는 것이다.

그럼 왜 sign bit를 안쓸까?? 지수부를 프로그램이 읽을 때 부호 비트를 따로 처리하지 않아도 된다는 간결함 때문에? 잘 모르겠다.

Leave a comment