본문 바로가기
시스템프로그램

[시스템프로그램]02-3-2 실수와 사칙연산(2)

by 케찹이 2020. 4. 30.

그럼 Willan Khan아저씨가 만든 IEEE Standard 754라는 실수 표현법 표준안이 어떻게 작동하는지 살펴보도록 한다. IEEE Standard 754는 거의 99퍼센트의 언어에서 사용하고 있지만 사용하지 않는 언어도 있다. 당장만 봐도 c언어에서는 적용되지 않을 때가 있다. 

 

실수는 (-1)^s * M * 2^E식으로 표현이 가능하다. 이것은 저번에도 봤었던 표를 식으로 나타낸것이다. 

-1^s 는 해당 실수가 양수인지 음수인지 판단하는 sign을 뜻한다. M은 위 그림에서의 fraction부분을 뜻하고 나머지 E는 exponent을 뜻한다. M은 fraction부분이지만 거의 1에서 2사이의 수가 된다. 일부로 1을 추가로 준것이다. 

 

주로 우리가 사용하는 컴퓨터는 32비트 또는 62비트를 사용하는데 실수 표현에서 이와 마찬가지로 32비트와 64비트를 사용한다. 32비트에서 1비트는 sign, 8비트는 exp비트를 표현하고 나머지 23비트는 fraction비트를 뜻한다. 그럼 64비트는 마찬가지로 1비트는 sing 비트, 11비트는 exponent 비트, 52비트는 fraction비트를 뜻한다. 이 부분은 뒤의 내용을 이해하기 위해서 알고 있어야 하는 부분이다. 

 

IEEE FP에선 3가지 encoding상황이다. 

1. Normalized

2. Denormalized

3. Special values

가 있다. 우리가 주로 앞으로 32비트를 주로 사용하니 32비트 컴퓨터로 예를 들겠다. exponent는 8비트이므로 최소값은 0, 최대값은 255가 올수 있다. 그리고 이 exponent가 0과 255가 아닐때 Normalized encoding을 사용한다. 다시 말하자면 exponent값이 모두 0이거나 모두1이 아닌 상황에 normalized을 사용한다. 

Denormalized는 exponent값이 모두 0일때 사용하고 special values는 exponent가 모두 1일때 사용하는 encoding 방식이다. 

 

그럼 Normalized values부터 자세히 살펴보자. 

일단 normalized value의 exponent는 방금 말한대로 exp가 모두 0이 아니고 모두 1도 아니다. 

처음 말했듯이 실수는 (-1)^s * M * 2^E으로 표현된다. sign비트는 한 비트만 사용하므로 설명할게 없고 M과 E를 알아야지 실수가 무슨 값인지 알수 있다. 일단 E부터 살펴본다.

E = Exp - bias이다. 

Exp값은 unsigned 값으로 exponent를 표현한 값이다.

bias가 무엇이냐면 저번 글에서 excess exp와 같은 놈이다. 그래서 Normalized에서 k비트를 사용할 경우

bias = 2^(k-1) -1값이 된다.

그래서 32비트의 bias는 single precision으로 불리며 127이 되겠고 64비트의 bias는 double precision이라고 불리며 1023이 되겠다. 32비트의 Exp는 1~254이고, E는 -126~127이 된다. 64비트의 Exp는 1~ 2046이고 E는 -1022 ~ 1023이 된다. 

 

그 다음 M값을 살펴본다. 

M은 소수를 표현하는 값이기에 0.xxxxx라고 나오는게 정상이지만 여기에 1를 더해서 표현을 하게 된다. 

M = 1 + f = 1.xxxx처럼 표현이 된다.

1의 값을 추가로 더 얻는 이유는 Willan Khan아저씨가 1을 추가적으로 주어지면 표현가능한 비트를 늘리면서 활용할 수 있는 방식이 많아진다고 했다. 구체적으로 어떻게 도움되는지는 다음 예제들을 살펴보자.

 

예로 2003.0이란 실수는 이진수로 표현하게 되면 11111010011 = 1.1111010011 * 2^10으로 표시된다.

M = 1.1111010011 ,   frac = 111110100110000000000000이 되겠다.

E = 10, Exp = E + bias = 10 + 127 = 137 = 100010001

sign = 0

 

0 10001001 1111010011000000000

s    exp          frac

 

 

그럼 이어서 denormalized value를 살펴보겠다.

denormalized value의 exp값은 모두 0일때이다. 그래서 원래는 E값이 항상 0 - bias여지만 Willam Khan 아저씨는 E를

E = 1 - Bias로 정했다.

그리고 M도 Normalized에는 1.xxxx로 표현됐지만 denormalized에선 0.xxxxxx로 표현된다. 

이렇게 굳이 정해주는 이유는 Gradual underflow라는 특징을 활용하기 위해서이다. Gradual underflow란 실수가 0에 가까워졌을 때 0에 닿기 위해서 만들어진 특징이다. 지금은 조금 안다가올 수 있다. 좀있다 그림을 통해서 이해해보자. 

 

Special Value는 exp가 모두 1일때의 값이다. 

exp가 모두 1이고 frac이 모두 0일때 그 값은 무한대라고 생각하면되겠다. sign비트에 따라 음수,양수인지는 판단가능하다.

그리고 frac이 0이 아닌 다른 수 일때는 Not a Number, NaN이라고 표시한다. 말그대로 숫자가 아닌 값들을 표현한다. 예를 들면 허수, 혹은 무한대에 계산을 진행하는 수들을 뜻한다. 

 

 

예제를 살펴볼텐데 32비트, 64비트는 정말 너무 큰 수와 너무 작은 수를 표현하기에 복잡하다. 그러므로 8비트로 우리가 배운 내용을 적용해본다. sign비트는 1비트, exp비트는 4비트, frac비트는 2비트를 차지한다. 

기본적으로 bias = (2^3-1) = 7 가 되겠다. 

 

먼저 Exponent쪽만 살펴 보도록 한다. exp은 4비트로 구성되어 있으며 0 ~ 2^4-1까지 표현이 가능하다. 그러니 normalized에선 exp값이 1~14까지 표현가능하다.  

 

일단은 처음 denormalozed인 smallest positive부터 살펴보자면 denormalized value의 E는 E = 1 - bias였다. 그러므로 denormalized value의 모든 E = 1 - 7 = -6이 된다. 그러므로 2^E값도 항상 1/64이다. 그럼 M을 살펴보기 위해 f(fraction)을 살펴보자면 fraction은  0.001이니 1/8이 된다. denormalized이선 M이 항상 1보다 작았으므로 M=f=1/8이된다. 그럼 V=2^E * M = 2^-6 * 1/8 = 1/512가 된다. 그리고 V는 표에 살펴보면 알 수 있듯이 fraction이 1늘때마다 순서대로 분자가 1씩 늘어난다. 

위 표의 결과값을 자세히 살펴보면 없는 값들이 군데군데 발견할 수 있다. 우리가 8비트수는 2^8 -1 = 255만큼 표현 가능한것으로 알고 있는데 무한대가 들어오기 마지막수가 240이다. 그래서 만약에 우리가 결과되어 나온 값이 230이라고 하면 230와 가까운 224가 출력이 된다. Float는 굉장히 큰 수와 작은 수를 표현하기 위해 만들었으므로 정수와 달리 표현하지 못하는 숫자가 있다. 물론 우리가 실제로 사용하는 컴퓨터에선 32, 64비트를 지원하기에 비정상적으로 작거나 큰 수가 아니면 거의 다 표현가능하다. 

 

위 그림은 실수의 표현가능한 범위를 설명해주는데 굉장히 큰수와 작은 수에 다가갈수록 표현할 수 있는 수가 적어진다. 그리고 exp가 같은 수끼리는 다음 수를 표현하는 수까지의 거리가 일정하다. 

예를 들자면 8비트에서 가장 큰 수인 240과 1 fraction차이나는 224와의 거리(차)는 16이 차이가 난다. 그럼 224보다 다음으로 작은 수는 224와 16차이가 나는 208이 된다. 그럼 16이란 차이가 exponent 1110 000까지 유지된다. 그리고 1101부터는 다른 간격으로 밑의 수와 차이가 나게된다. 

근데 위는 일반적인 경우 Normalized한 경우이다. 그럼 denormalized는 어떤식으로 간격이 일정하게 되냐면 바로 가장 작은 Normalized의 exp과 같은 간격으로 숫자를 표현한다. 이런 이유는 0을 표현가능하기 위해서다. 만약에 Normalized식으로 exp가 작아질수록 거리가 작게 되면 영원히 0에 닿을 수 없다. 그래서 denormalized는 normalized의 최소값과 같은 간격으로 숫자를 표현한다. 이게 바로 앞서 설명한 Gradual underflow이다. 

 

 

마지막으로 두 실수를 비교하는 방법이다. 두 실수를 비교하는 방법은 몇가지만 살펴보면 굉장히 쉽게 비교할 수 있다. 

첫번째로 sign비트를 비교하고 두번째론 NaN인지를 확인하고 세번째론 denormalized인지 normalized인지를 확인하고 나머지는 exp와 frac만 확인하면 두 실수의 크기를 쉽게 비교할 수 있다. 

댓글