본문 바로가기

진법과 컴퓨터의 수 표현

자릿값으로 진법을 바꾸고 이진 정수·2의 보수·부동소수의 한계를 계산합니다.

십진수 13과 이진수 1101은 같은 값의 다른 표기입니다. 비트 수까지 정하면 표현 가능한 범위도 정해집니다. 수의 체계를 읽은 뒤 자릿값 변환, 음수 표현, 소수 오차를 연결해 익힙니다.

자릿값과 변환

기수 bb에서 한 자리 숫자는 0부터 b−1b-1까지입니다. 정수 부분은 b0,b1,b2,…b^0,b^1,b^2,\ldots, 소수 부분은 b−1,b−2,…b^{-1},b^{-2},\ldots의 무게를 가집니다. 따라서 (1101.01)2=8+4+1+1/4=13.25(1101.01)_2=8+4+1+1/4=13.25입니다. 16진수는 10부터 15까지의 값을 A부터 F까지의 문자로 쓰며 한 자리가 4비트에 대응합니다. (2D)16=2⋅16+13=45(2D)_{16}=2\cdot16+13=45이고 이진수로는 0010 1101입니다.

십진 정수 45를 2로 계속 나누면 몫·나머지가 (22,1),(11,0),(5,1),(2,1),(1,0),(0,1)(22,1),(11,0),(5,1),(2,1),(1,0),(0,1)입니다. 나머지를 거꾸로 읽어 101101을 얻습니다. 소수 0.625는 2를 반복해서 곱합니다. 0.625⋅2=1.250.625\cdot2=1.25에서 1, 0.25⋅2=0.50.25\cdot2=0.5에서 0, 0.5⋅2=1.00.5\cdot2=1.0에서 1을 차례로 취해 (0.101)2(0.101)_2입니다. 정수는 역순, 소수는 나온 순서입니다.

올림과 빌림은 기수만 바꾼다

2의 보수에서 '1을 더한다'를 읽기 전에 이진 덧셈을 확인합니다. 한 자리의 합이 2이면 0을 쓰고 다음 자리에 1을 올립니다. (1011)2+(0110)2(1011)_2+(0110)_2를 오른쪽부터 계산하면 1+0=1, 1+1=2이므로 0과 올림 1, 0+1+올림 1=2이므로 0과 올림 1, 1+0+올림 1=2이므로 0과 마지막 올림 1입니다. 결과 (10001)2(10001)_2는 11+6=17과 일치합니다.

뺄셈에서 빌려온 한 자리는 기수 2만큼입니다. (10000)2−1(10000)_2-1은 왼쪽의 16을 8+4+2+2로 나누어 끝자리에서 2−1=1을 남기므로 (01111)2=15(01111)_2=15입니다. 16진수에서도 F+1=16이라 (10)16(10)_{16}으로 올립니다. 규칙은 자리 합이 기수 b에 도달하면 다음 자리에 1을 올리는 것입니다. 여기서는 변환과 2의 보수에 필요한 작은 계산을 연결하며 모든 진법의 긴 곱셈·나눗셈을 다루지는 않습니다.

비트 수와 음수

부호 없는 ww비트 정수는 0~2w−12^w-1입니다. 4비트에서 1111은 15입니다. 같은 비트에 2의 보수 부호 해석을 적용하면 최상위 자리의 무게가 −2w−1-2^{w-1}이 되어 1111은 −8+4+2+1=−1-8+4+2+1=-1입니다. 비트열만으로 부호 해석을 확정할 수 없습니다.

4비트에서 -3을 만들려면 +3인 0011의 비트를 뒤집어 1100으로 만들고 1을 더해 1101을 얻습니다. 범위는 -8~7입니다. 0111(+7)에 0001을 더하면 1000(-8 해석)이 됩니다. 정수의 수학적 합 8이 표현 범위를 벗어난 것이며, 하위 비트만 보존하는 계산을 일반 정수의 결합법칙과 혼동하지 않습니다. 언어별 오버플로 처리도 다릅니다.

부동소수는 유한 정밀도 표현

부호·유효숫자·지수로 수를 표현하는 방식은 매우 작거나 큰 수를 다루기 좋지만 비트 수가 유한합니다. 유한 이진소수로 표현할 수 있는 기약 유리수의 분모는 2의 거듭제곱입니다. 1/101/10의 분모에는 5가 있어서 이진 전개가 끝나지 않습니다. 저장할 때 반올림하므로 0.1과 0.2를 더한 값이 저장된 0.3과 조금 다를 수 있습니다.

from fractions import Fraction
print(Fraction(1, 10) + Fraction(2, 10))  # 3/10, 정확한 유리수 계산
print(0.1 + 0.2 == 0.3)                 # 일반적인 Python float에서 False

이는 유리수가 무리수가 된 것이 아닙니다. 유리수 1/10의 유한 이진 표현이 불가능한 것입니다. 근삿값 비교에는 오차 크기·단위에 맞는 허용오차를 선택하고, 금액처럼 십진 정밀도가 필요한 계산에서는 정수 최소단위나 적절한 십진 타입을 검토합니다.

스스로 풀어보기

문제 1. (10110.11)2(10110.11)_2를 십진수로 바꾸세요.

힌트: 정수 자리와 소수 자리의 무게를 따로 더합니다.

풀이: 16+4+2+1/2+1/4=22.7516+4+2+1/2+1/4=22.75입니다. 이진 소수 둘째 자리의 무게는 0.01이 아니라 1/41/4입니다.

문제 2. 8비트 11111011을 부호 없는 정수와 2의 보수 정수로 각각 읽으세요.

힌트: 부호 해석은 최상위 비트의 무게를 바꿉니다.

풀이: 부호 없으면 128+64+32+16+8+2+1=251128+64+32+16+8+2+1=251입니다. 2의 보수이면 251에서 256을 빼 -5입니다. 뒤집기 00000100에 1을 더해 00000101을 얻는 방법으로 절댓값 5도 확인할 수 있습니다.

진법 계산이 막히면 bkb^k 자릿값으로 돌아가세요. 컴퓨터 장치의 실제 데이터 표현은 컴퓨터구조, 명제의 0·1 표현은 부울대수에서 연결합니다.