Little Jay

[CS] Floating Points - Fixed Point Representation(IEEE) 실수 자료형 - Computer System 3rd Edition by Bryant 본문

Univ/System Programming

[CS] Floating Points - Fixed Point Representation(IEEE) 실수 자료형 - Computer System 3rd Edition by Bryant

Jay, Lee 2022. 2. 24. 18:54

지난 포스팅에 이어 이번에는 실수자료형에 대한 이야기를 해보고자 한다. 

세상은 정수로만 이루어 진 것이 아니며, 당연하게도 실수형을 가진다.

예를 들어 3.141592...... 이런 수들을 실수라고 한다.

이러한 실수는 특히 과학 분야에서는 이 소수점 표현들이 중요해진다. (유효범위때문에 물리학 성적 읍읍......)

 

Fixed Point Representation

실수 자료형에는 floats, double 등이 있다. 

이러한 자료형을 표현하는 것을 Fixed Point Representation이라고 부른다. 

 

 

 

 우리는 항상 bit를 사용할 때 2진수 체계를 사용하며, 이는 당연하게도 소수점을 표기할 때도 동일하게 적용이 된다. 2의 -1승은 1/2이고 이렇게 해서 2의 거듭제곱의 표현으로 표현이 가능하다. 수식으로 표현하자면 아래와 같다.

 하지만 이렇게 일반적으로 실수를 표현하는 방식은 여러 문제점이 존재한다.

3.4375(10) = 11.0111(2) 이렇게 표현하는 것은 직관적이지만, 먼저 순환소수의 문제점에 봉착한다.

순환소수가 궁금하다면 여기를 참고하는 것이 좋을 듯 하다. 

1/3 같은 경우는 0.0101010101010101010101.......[01]로 순환하고,

1/5 같은 경우도 0.00110011001100110011......[0011]로 순환하고 컴퓨터가 이를 해석을 해야하는 문제점이 생긴다.

그리고 다른 문제는 w bits 의 자료형을 선언 했다면 결국 우리는 이 w 라는 범위 안에서만 수를 표현해야하기에

자료형이 매우 커지거나 매우 작아진다면 표현할 수 없거나, 메모리 낭비 등의 난관을 마주칠 수 있다. 

 

IEEEE Floating Point

그래서 IEEE에서는 IEEE 754라는 표준 규약을 1985년에 만들어서 부동 소수점에 문제를 해결했다.

많은 프로그래밍 언어에서 IEEE 표준을 따르도록 정의하고 있다.

 이제 어떻게 부동소수점, 즉 실수가 컴퓨터, 다시말해 메모리에 어떻게 저장이 되는지 설명을 하겠다.

먼저 앞의 s는 sign bit이라고 한다. 즉, 이는 수가 양수인지, 음수인지 결정을 해주는 것이다. 

다시말해 이를 부호 비트라고 지칭한다. 

이 부호 비트는 (-1)^s 의 꼴인데, s가 1이면 음수, 0이면 양수로서 해석한다. 

frac 부분은 Mantissa의 분수꼴의 형태이다. 

그리고 exp는 exponent이며 2의 거듭제곱 꼴의 형태이다.

결과적으로는 V = (−1)^s ×M × 2^E 로 표현이 된다.

이게 어떤 의미인지 예시와 함께 설명을 자세히 진행하겠다.

 

먼저 single precision은 float, 32bit의 표현이고, double precision은 double, 64bit의 표현이다.

먼저 single precision은 위의 부분을 보면 알 수 있듯이 sign bit 1개, exp 8개, frac 23개의 bit으로 구성이 되어 있고, 

double precision은 sign bit 1개, exp 11개, frac 52개의 bits 들로 이루어져 있다.

 

single precision의 bias는 exp의 개수가 8개 이므로 0~255의 반인 127이 된다. 

double precision은 0~2047의 반인 1023이 bias가 된다. 

그래서 위 수식의 E는 biased된 value라고 한다. 

그래서 E는 E = exp - Bias가 된다. 

 

1(10)은 이진수 1(2)와 같다. (우선 이게 single precision이라고 가정하자. 1.0f)

1(2) = 1.0 x 2^0 으로 변환하여 쓸 수 있다.

여기서 2^0의 0이 바로 E의 부분이다. 

E가 0이고 8bit를 사용하고 있기 때문에 0 = exp - bias(127)이라는 식을 맞춰줘야 한다.

당연하게도 exp는 127이 되야하며 이는 8bit으로 0111 1111이 된다. 

그리고 1.0 x 2^0에서 1.0 즉 이 부분이 Mantisaa인데, 1.0000...... 이므로 frac 부분도 0으로 가득 채워진다.

즉 frac 부분은 소수점 부분들 이라고 생각하면 된다. 

그래서 메모리에는 00111111100000000000000000000000 로 저장이 된다. 

 

이번에는 다른 예시를 들어보자. 2.75f(10)이라는 수가 있다고 해보자.

이를 당연하게 bit level로 표현하면 10.11(2)가 된다. 

그러면 우리는 이를 1.xxx 의 꼴로 맞춰주기 위해 이를 1.011 x 2^1 로 변형해줄 수 있다.

양수이기에 sign bit는 0으로 고정이 되었고, 이번에 1 = exp - 127이기 때문에 exp는 1000 0000이 된다.

이번에 frac 부분은 011이라는 부분이 있기에 01100000000000000000000 가 되는 것이다.

이를 다시 정리하면 01000000001100000000000000000000으로 저장이 된다. 

 

이번에는 우리에게 익숙한 3.14f를 분석해보자.

3.14를 이진수로 변환하면 11.001000111101011100001010 이 된다.

이를 다시 1.xxx 꼴로 변환을 해주면 1.1001000111101011100001010 x 2^1이 된다.

마찬가지로 sign bit 0, exp = 1 + 127, frac은 1001000111101011100001010이 되겠지만 아쉽게도 우리는 32bit를 맞춰주어야 하기 때문에 뒤의 10은 삭제된다. 

이를 다시 정리하면 01000000010010001111010111000010으로 저장이 된다. 

 

이번에는 마지막으로 15213.0을 저장해보자.

우선 이를 이진수로 변환하면 111011101101101이고 이를 다시 꼴을 맞춰주면,

1.1101101101101 x 2^13이 된다.

13 = exp - 127 이므로 exp는 140, 즉 10001100이 된다.

frac도 23개 이하이므로 그대로 들어가게 되면 

01000110011011011011010000000000으로 저장이 된다.

 

8byte float의 예시를 살펴보았는데, 16byte double도 이와 똑같고 사실 bias가 1023으로 바뀐 것 밖에 없다.

예를 들어, 01000000010100101010000000000.... 의 bit가 double 형태로 저장이 되어있다고 가정해보자. 

sign bit가 0이므로 이는 당연히 양수고, 앞서 11bit의 exp를 가진다고 했으므로, 10000000101이 exp이다.

이는 1029이고, 1029-1023 = 6이다. 

그러면 1.00101010...... x 2^6으로 변환시킬 수 있으므로, 1001010.10.......0 은 74.5가 된다. 

 

Reference

Randal E. Bryant, & David R. O’Hallaron. (2016). Computer Systems A Programmer’s Perspective Third edition. Carnegie Mellon University: Pearson.

Comments