저번에는 정수를 표현하는 법을 봤다. 이번엔 실수를 표현하는 법을 보겠다.
소수점 표시 방법
크게 두가지가 있다.
고정 소수점 방식은 숫자에서 소수점의 위치를 고정시켜셔 숫자를 표시하는 것이다.
예를들어 소수점 4번째 자리에서 고정한다고 하면
가장 큰 숫자는 9999.9999이고, 가장 작은 숫자는 0000.0001이다.
우리가 이번에 배울 부동소수점 방식은 소수점의 위치를 따로 정해두지 않는다.
따라서 숫자 내에 유효숫자와 소수점의 위치를 표시한다.
예를 들어 8자리 유효숫자와 2자리 지수로 표현할 때, 9.99999999E+50으로 표시할 수 있다.
여기서 9.99999999가 유효숫자이고 E+50이 지수이다.
2진 소수

우리가 이제까지 이진수를 사용하여 정수를 표시할 때에 맨 오른쪽부터 2의 0제곱, 2의 1제곱.... 이런식으로 곱해나가면서 더했다.
하지만 2진 소수에서는 소수점도 존재하여, 소수점 이전 부분은 똑같이 하되, 소수점 이후 부분은 2의 -1제곱(1/2), 2의 -2제곱(1/4)... 이런식으로 표현한다.

앞의 내용을 이해했다면 위 그림이 어떤 방식으로 변환된 것인지 이해했을 것이다.
논리회로에서도 아마 배웠을텐데 한번 더 이야기 하자면
2진 소수에서 우측으로 쉬프트 하면 전체에 2를 곱한 효과가 있고, 좌측으로 쉬프트하면 2를 곱하는 효과를 얻는다.
그리고 2진소수에서 0.111111111111은 1에 아주 근접한 숫자일 것이다(1/2 + 1/4+ 1/8+ ......) 이 경우

이런식으로 표기한다.
10진 소수를 2진 소수로 변환

0.625를 2진소수로 변환해보자.
이건 해당 숫자의 소수점 밑에자리 수에다가 2를 계속 곱했을 때의 정수자리의 숫자를 모으면 된다(그림참고)
위에서는 순서대로 101이 나오므로, 답은 0.101임을 알 수 있다.
한계
2진 소수의 경우 2의 제곱수로만 표시하기 때문에 모든 소수를 정확하게 표시가 불가능하다
또한 소숫점 이하의 비트들이 무한반복되는 경우, 정확히 표시가 불가하다

패트리엇 미사일 예제

위를 보면 0.1의 근사값을 이용한다고 쓰여있다. 근사값이라면 1.0과 완전히 같지는 않은 값으로, 오차가 무조건 있을수밖에 없다.
패트리엇 미사일 예제는 이런 오차가 쌓이고 쌓여서 결국엔 사고가 난 사례이다.
여기서 실제값인 0.1에서 근사값 x를 뺀 값은 9.54*10^(-8)이다. 이렇게만 보면 매우 작다.
하지만 이 시스템을 100시간동안 동작시키면
100 * (3600 * 10(1시간동안 클럭 수)) * 9.54*10^(-8)이면 34.3*10(-2)초이다. 즉 이만큼의 시차가 있다는 소리이다.
그럼 이 미사일이 초속 2000미터의 속도로 날아가면 1000시간 후 의도했던 도착지점과의 거리는 0.343 *2km/s = 0.6868km이다.
즉 이러한 오차가 발생했을 때 목표지점보다 0.6868km 떨어진 곳에 도착하게 되는 것이다.
IEEE Floating Point 표준
이제 우리가 주로 사용하는 소수의 표현 방법을 알아볼 것이다.

기본적인 포멧은 위와 같다. 10진 소수에서 2진 소수로의 인코딩, 디코딩을 할 때 S,M,E값이 필요하다
이전에는 우리가 그냥 비트대로 연산만 하면 10진 소수가 나왔지만, 이 방식에서는 우리가 비트수에서 s,m,e값을 추출(?)해서 표준 규칙에 따라 계산을 해야한다.

위와 같이 특정 비트가 있을 때 s는 무조건 첫 하나의 비트이고, ~에서 ~번째 비트까지를 exp로 할지 frac로 할지?는 미리 규칙에 따라 정해져있다.

위와 같이 정의되어있는데, 32비트를 인코딩할때는 8개의 비트는 exp, 나머지 23개의 비트는 frac로 쓴다는 것이 약속되어있다.
이 값들을 어떤 방법으로 인코딩(10진 소수로 변환)할건지는 총 세가지 경우에 따라 다르다
정규화된 값(Normalized values)

기본 포맷은 위와 같다.
s비트는 -1의 제곱수이므로, s가 1이면 전체 실수가 음수, 0이면 양수이다.
그리고 m값은 frac 값, e값은 exp값과 관련된 값이다.(2진수 그대로 10진수로 변환하면 됨)
정규화된 값으로 인코딩하기 위한 조건은 exp 값의 모든 비트가 0이거나 1이 아니면 된다.(000....0 or 1111...111)
여기서 중요한 것은 exp 값이 그대로 E값 그 자체가 아니라는 것이다.
지수 E는 음수가 될수도 있다. 하지만 exp 내부에 음수를 직접 표시할수가 없다(비부호성) . 따라서 exp는 보정된 값을 사용한다.
공식은
E = exp - bias
exp = E + bias이다. 여기서 bias는 조정값으로, 2^(e-1) - 1이다.
예를들어 exp 총 비트수가 4면 bias는 7이 된다.
총 비트수가 4이면 표현 가능한 수는 0~15이다. bias값을 통해 보정한다면 이 값을 통해 표현할 수 있는 E값은 -7에서 8이 된다.
그 다음 frac 값이다. frac 값 역시 실제 M값은 아니다.
정규화 된 값에서 유효숫자 M은 묵시적으로 1로 시작하는 것으로 간주한다,
즉 예를들어 frac 값이 11101이라고 해보자. 그러면 우리는 M값을 1.11101이라고 인코딩할 수 있다.
따라서 M값의 최소값은 frac가 모두 0일때, 즉 1.00000일때 1이고, 최댓값은 1.1111111 즉, 2보다 약간 작을 때(2일수는 없다)가 된다.
이에따라 우리는 소수점 위 첫째자리인 1을 따로 frag값에 표시하지 않아도 얻게 되었다. (11101만 표시했는데, 1.11101이라는 수를 얻게 되었으므로) 따라서 1비트를 무료로 표시할 수 있게 된 것이다.
이제 전체 예제를 보자

15213을 2진 소수로 변환하려고 한다. 일단 15213을 2진수로 변환하면 위와 같다. 우리는 ieee로 변환해야하므로 소수점 위 한자리만 남겨놓고, 나머지는 다 오른쪽으로 밀어 M값을 만든다. 이 때 frag값을 m값으로 변환할 때 소숫점 위 1의자리수는 무조건 1이라고 가정하므로, 소수점 위 한자리는 꼭 1이어야한다.
이렇게 해서

M값이 만들어졌다. frac값은 소수점 밑에 자리 수들 이므로 110 .... 이들 전체가 frac값이라고 할 수 있다.
이로서 frac값을 구했다.
이제 exp 값을 구해보자.
위에 변환된 것을 보면 우리의 지수값은 13이다. 즉 E값은 13이다.
우리가 변환하고자 하는 수는 exp 값이 8비트 주어졌다. 그러면 bias값은 2^(8-1)-1 = 127이다.
exp값은 E + bias이므로, exp는 140이다. 140을 2진수 변환하면 1000 1100이므로 이 값이 exp라는 것을 알 수 있다.

위의 값이 최종값이다.
맨 앞 값은 S인데 15213은 양수이므로 0이다. 그리고 바로 뒤에는 우리가 구한 exp 값이 들어가있고, 그 뒤에는 frac 값이 들어가있다.
이 때 frac 값은 아까 말했듯이 가장 앞 1은 무료로 표시할 수 있으므로 생략되었다.(빨강 1 뭔지 헷갈릴까봐 다시 설명)
비정규화 인코딩
비정규화 인코딩의 방법으로 변환하려면 모든 exp 비트가 0이어야 가능하다.
비정규화에서 E 값을 구하는 방법은 그냥 1에서 bias 값을 빼주면 된다. 당연히 음수가 나오는데 음수가 나오는게 맞다!(자세한건 뒤에서)
비정규화에서 M값을 구하는 방법은 정규화와 비슷하다. 하지만 다른 점은 아까는 소숫점 위 1의자리수를 무조건 1로 뒀었는데 이번에는 그 자리에 0을 넣는다.
즉, 만약 frac 값이 1010이었으면 여기서의 M값은 0.1010이다.(정규화였으면 1.1010)
비정규화 인코딩은 크게 두가지로 나뉜다.
exp = 0.000..., frac = 0.0000
exp와 frac가 모두 0으로 채워졌을 경우, 0을 의미한다.
exp = 0.000..., frac != 0.0000
exp 가 0인데 frac가 0이 아닐 경우, 0.0에 매우 근접한 소수값을 표시한다.
무슨말인가 하면
예를들어 exp 비트수가 4라서 e값을 -7에서 8까지만 표시할 수 있다고 해보자
우리는 0.0000000010000 을 변환해야한다. 이 때 아까처럼 소숫점 위에 1의자리수를 1로 만들기 위해(1.010xxx이런거처럼) 왼쪽으로 쭉 밀어야한다. 이 때 우리는 -7까지만 표현 가능하므로, 7비트만 밀 수 있다.
0.10000이 된다. 최대한 밀었는데 첫째자리수가 0이다. 이 때 정규화의 방식대로 인코딩을 한다면 1번째 자릿수를 1로 채울 것이다. 이렇게 하면 의도된 값이 나오지 않는다.
따라서 우리는 이렇게 디코딩을 할때에도 일의자리수가 0임을 알리기 위해서 exp값을 모두 0으로 두어 표시한다.
-> exp가 모두 0이네! 비정규화구나 frac가 1000이니까 M값은 0.1000이겠다! 가 가능하다
즉, 이 경우에는 0.00000001보다 작은 숫자를 표시할 수 있게 된다.
특수값
이 경우는 exp 비트가 모두 1인 경우이다.
여기도 크게 두가지 경우가 있다.
exp = 1111...1, frac = 0000...000
이 경우 무한대를 의미한다. 그냥 규칙이고, 오버플로우를 표시할 수 있다.
exp = 1111...111, frac != 000...00
이 경우 숫자로 표시할 수 없는 결과(NaN)을 나타낸다. (무한대 * 0, 무한대 * 무한대 등)
예제


예제는 각자 해보자. 9.6875같은 수가 있을 때 소숫점 윗 부분(9)와 아랫부분(6875)를 따로 2진수 변환해서 계산해나가면 된다.
출처
충남대 김형신교수님 시스템프로그래밍 강의자료
ESLAB | Home
eslab.cnu.ac.kr
'CSE > 시스템프로그래밍' 카테고리의 다른 글
| [시스템프로그래밍] 2장 정보의 표현 및 처리(정수의 표현) (1) | 2025.10.11 | 
|---|---|
| [시스템프로그래밍] 1장 컴퓨터 시스템 (2) | 2025.09.25 | 
| [BombLab] 환경설정(맥북 사용자) (2) | 2024.10.06 | 
| [BombLab] phase_6 해설 (2) | 2024.09.11 | 
| [BombLab] phase_5 해설 (1) | 2024.09.10 | 
 
										
									 
										
									 
										
									