정수는 "자연수(양의 정수)"와 "0", "음의 정수"로 구성된 수 집합입니다. 컴퓨터에서도 정수의 의미 자체는 동일합니다. 그러나, 컴퓨터는 2진수를 활용하여 수를 표현하기에 정수 표현 방법은 약간 특이합니다. 지금부터 컴퓨터는 정수를 어떻게 표현하는지 알아보겠습니다.
부호없는 정수(Unsigned Integer)
말 그대로 부호를 생략한다는 의미로, 모든 숫자는 0 또는 양의 정수로 표현됩니다.
8비트로 부호 없는 정수를 표현하면 $0_{10} ~ 255_{10}(= 2^8 - 1)$ 표현이 가능합니다. 즉, n비트를 사용한 부호 없는 정수 표현은 0부터 $(2^n -1)$ 까지입니다.
오버플로우(Overflow)
8비트로 표현하는 부호 없는 정수의 경우 $0 ~ 255$까지 가능한데 이때, 255를 넘어가는 숫자가 들어온다면, 컴퓨터는 틀린 값을 냅니다. 이를 "오버플로우(overflow)"라고 합니다. 즉, 오버플로우는 표현할 수 있는 가장 큰 절대값 수를 넘어서서 정확한 수를 표현할 수 없게 되는 경우를 말하는 것입니다. 오버플로우가 일어나서 연산 결과가 틀리더라도 프로그램은 계속 수행되기에 이를 명시적으로 체크해야 합니다.
CAUTION! : 오버플로우는 꼭 부호없는 정수에서만 나타나는 것은 아닙니다. 부호있는 정수와 실수에서도 오버플로우는 발생 가능합니다.
부호있는 정수(Signed Integer)
부호있는 정수는 본격적으로 "음수의 표현"을 다루겠다는 의미를 가지고 있습니다. 부호있는 정수를 표현하는 방법은 "부호화 절대값 표현"과 "보수 표현"이 있습니다.
부호화 절대값(Sign and Magnitude)
부호화 절대값 표현은 MSB(Most Significant Bit: 가장 왼쪽의 비트)가 0이면 '0 또는 양의 정수'를 MSB가 1이면 '0 또는 음의 정수'를 나타내는 방식입니다.
$$ 0000 \, 0101_2 \rightarrow +5_{10} \\
1000 \, 0101_2 \rightarrow -5_{10} $$
8비트를 이용하여 부호화 절댓값을 표현할 떄는 절댓값 계산을 위해 7비트까지만 사용할 수 있습니다.
즉, n비트를 사용한 부호 있는 정수 표현은 $-(2^{n-1} -1)$부터 $+(2^{n-1} -1)$ 까지이다.
이러한 부호화 절대값 표현에는 문제점이 있는데, 첫 번째는 "부호화 절대값 표현에는 +0과 -0, 즉 0이 2개가 존재한다"는 것입니다. 두 번째는 "부호화 절대값 표현을 통한 덧셈 연산은 아주 느리다"는 것입니다.
이러한 문제점들을 보완하고자 "보수 표현"이 탄생하게 되었습니다.
보수 표현(Complement Representation)
보수는 "두 수의 합이 진수의 밑수(N)가 되게 하는 수"를 말합니다. 예를 들어 "10진수 2"의 10의 보수는 "10진수 8"이고, "10진수 6"의 10의 보수는 "10진수 4"이다.
n진법으로 표시된 정수를 기준으로 n-1의 보수 표현법과 n의 보수 표현법이 존재합니다.
대표적으로 컴퓨터가 사용하는 2진법에는 1의 보수와 2의 보수가 있는데 이에 대해서 알아봅시다.
(1) 1의 보수 표현
1의 보수는 "어떤 2진수의 비트를 반전"시켜서 얻을 수 있습니다.
즉, 0 -> 1, 1 -> 0로 바꾸는 것입니다. {Ex) 2진수 1010의 1의 보수는 0101입니다.}
1의 보수 표현에는 0이 +0과 -0 이렇게 2개 존재합니다.
(2) 2의 보수 표현
2의 보수는 "어떤 2진수의 비트를 반전시킨 후 결과값에 1을 더해서" 얻을 수 있습니다.
즉, 어떤 2진수를 1의 보수로 바꾼 후 제일 뒤에 1을 더해주는것과 같습니다. {Ex) 2진수 1010의 2의 보수는 0110입니다.}
2의 보수 표현에는 0이 1개만 존재하기에 1의 보수 표현에 비해 음수를 1개 더 표현이 가능합니다.
컴퓨터는 기본적으로 2의 보수 표현을 사용합니다.
(3) 보수 표현 사칙 연산
덧셈: 2진수에서 덧셈은 10진수에서 덧셈과 계산 방식이 동일합니다. {Ex) 2진수 0101 + 2진수 0110 = 2진수 1011}
뺄셈: 2진수에서는 뺄셈 계산이 불가능하기에 보수를 이용하여 계산해야 합니다.
1의 보수 뺄셈
가장 먼저 빼는 수의 1의 보수를 구한 후 더합니다.
그 후, 덧셈결과에 자리올림이 생기면 최하위 비트에 1을 더한후 자리올림 된 수를 제거합니다.
그 후, 덧셈결과에 자리올림이 생기지 않으면 "연산 결과"의 1의 보수를 구한 후 '-' 부호를 붙입니다.
Ex) 2진수 1101 - 2진수 1001
=> 1101 + (1001의 1의 보수)
=> 1101 + 0110 = 10011
=> (최하위 비트에 1 더함 = 10100)
=> (자리올림 수 제거 = 0100)
=> 답은 0100입니다.
Ex) 2진수 0101 - 2진수 0110
=> 0101 + (0110의 1의 보수)
=> 0101 + 1010 = 1111
=> (1111의 1의 보수 = 0)
=> (부호 붙여서 -0)
답은 -0입니다.
2의 보수 뺄셈
가장 먼저 빼는 수의 2의 보수를 구한 후 더합니다.
그 후, 덧셈결과에 자리올림이 생기면 자리올림이 생긴 수를 제거한다, 그리고 그 값이 결과이다.
그 후, 덧셈결과에 자리올림이 생기지 않으면 "연산 결과"의 2의 보수를 구한 후 '-' 부호를 붙인다.
Ex) 2진수 1101 - 2진수 1001
=> 1101 + (1001의 2의 보수)
=> 1101 + 0111 = 10100
=> (자리올림 수 제거 = 0100)
=> 답은 0100입니다.
Ex) 2진수 0101 - 2진수 1001
=> 0101 + (1001의 2의 보수)
=> 0101 + 0111 = 1100
=> (1100의 2의 보수 = 0100)
=> (부호 붙여서 -0100)
답은 -0100입니다.