컴퓨터를 포함한 각종 논리회로에서 음수를 표현하는 방법은 다음 3가지가 있다.
- 부호 절대값 (Sign-Magnitude)
- 1의 보수 (1's Complement)
- 2의 보수 (2's Complement)
그런데 실제로 널리 사용되는 것은 2의 보수 방식이다. 이유는 회로가 간단해지기 때문이다. 위의 세가지 방식을 각각 살펴보면서 장·단점을 비교해 보자.
1. 부호 절대값 (Sign-Magnitude)
부호 절대값 방식은 가장 쉽게 생각할 수 있는 방식이다. MSB(최상위비트)을 부호비트(0이면 양수, 1이면 음수)로 사용하고, 나머지는 절대값을 표현한다. 4비트 정수를 예로 들면,
0000 +0 1000 -0
0001 1 1001 -1
0010 2 1010 -2
0011 3 1011 -3
0100 4 1100 -4
0101 5 1101 -5
0110 6 1110 -6
0111 7 1111 -7
그런데 부호 절대값 방식에는 몇 가지 문제가 있다. 우선 0이 두 개(+0과 -0)나 존재하기 때문에, 둘 다 0으로 인식하도록 해야 한다. 심각한 문제는 덧셈과 뺄셈을 할 때이다. 인간이 직접 계산할 때처럼 부호와 절대값을 따로 분리해서 계산해야 하고, 음수를 더함으로써 뺄셈을 구현할 수가 없어서 뺄셈기를 따로 구현해야 한다. 그러면 인간이 덧셈과 뺄셈을 수행할 때의 과정을 살펴보자.
2(10) + 3(10) = 0 010 + 0 011 = 0 101 = 5(10)
(양수끼리 더했으므로 양수) <덧셈기 사용>
-2(10) + -3(10) = 1 010 + 1 011 = 1 101 = -5(10)
(음수끼리 더했으므로 음수) <덧셈기 사용>
3(10) - 2(10) = 0 011 - 1 010 = 0 011 = 1(10)(절대값이 큰 수에서 작은 수를 뺐으므로 양수) <뺄셈기 사용>
2(10) - 3(10) = 0 010 - 1 011 = -(011 - 010) = 1 001 = -1(10)
(절대값이 작은 수에서 큰 수를 뺄 경우에는 순서를 바꿔서 빼고 결과는 음수) <뺄셈기 사용>
인간에게는 매우 쉬운 일이지만, 위의 모든 사항을 고려하여 계산을 수행하는 회로를 만드는 것은 쉬운 일이 아니다. 그리고 <, >, <=, >= 등의 비교연산을 수행할 때 다음과 같은 모순이 생긴다.
3(10) > 2(10) = 0011 > 0010 = TRUE
-2(10) > -3(10) = 1010 > 1011 = FALSE (???)
위와 같이 음수의 경우는 반대가 되므로 이를 구분해야 한다. 사실 비교연산은 뺄셈을 한 후 결과의 부호를 가지고 판단하기 때문에 이는 덧셈과 뺄셈 문제와 동일하다.
2. 1의 보수 (1's Complement)
1의 보수 방식은 부호 절대값 방식에서 단순히 음수의 순서를 뒤집은 것이다.
0000 +0 1000 -7
0001 1 1001 -6
0010 2 1010 -5
0011 3 1011 -4
0100 4 1100 -3
0101 5 1101 -2
0110 6 1110 -1
0111 7 1111 -0
음수의 순서를 뒤집기만 한 것이라 별것 아닌것 같지만 사실 엄청난 유리함이 있다. 우선 재미 있는 성질이 하나 생긴다. 비트를 반전시키면 부호가 바뀌게 된다. 다행히 비트반전은 쉽게 구현할 수 있다. 그리고 MSB가 0이면 양수, 1이면 음수라는 성질은 그대로 유지된다.
3(10) = 0011 >> 1100 = -3(10)
-6(10) = 1001 >> 0110 = 6(10)
뿐만 아니라 부호 절대값 방식에서 골치거리였던 것이 깔끔하게 해결된다. 부호와 절대값을 따로 계산하지 않아도 되고, 음수를 더하는 방식으로 뺄셈을 할 수 있게 된다. 단, 캐리가 발생하면 LSB(최하위비트)에 1을 더해줘야 한다.
2(10) + 3(10) = 0010 + 0011 = 0101 = 5(10) <덧셈기 사용>
-2(10) + -3(10) = 1101 + 1100 = 1001 + 0001 = 1010 = -5(10) (캐리 발생) <덧셈기 사용>
3(10) - 2(10) = 0011 + 1101 = 0000 + 0001 = 0001 = 1(10) (캐리 발생) <덧셈기 사용>
2(10) - 3(10) = 0010 + 1100 = 1110 = -1(10) <덧셈기 사용>
어째튼 덧셈과 뺄셈이 매우 간단해졌다. 음수의 비교연산 모순도 해결되었다.
3(10) > 2(10) = 0011 > 0010 = TRUE
-2(10) > -3(10) = 1101 > 1100 = TRUE
그런데 여전히 0이 두 개인 것과 캐리를 처리해야 하는 문제가 남아있다. 즉, 0000과 1111을 둘 다 0으로 처리해야 하고, 계산과정에 캐리가 발생됐는지 감시해서 LSB에 1을 더해주는 회로를 구성해야 한다.
3(10) - 3(10) = 0011 + 1100 = 1111 >> 0000
게다가 위와 같이 실제 계산과정에서 발생하는 0은 항상 -0인 1111이다.
3. 2의 보수 (2's Complement)
2의 보수 방식도 단순해서 그저 눈에 거슬리는 -0을 없애기만 한 것이다.
0000 0 1000 -8
0001 1 1001 -7
0010 2 1010 -6
0011 3 1011 -5
0100 4 1100 -4
0101 5 1101 -3
0110 6 1110 -2
0111 7 1111 -1
-0이 없어지고 대신 -8(10)이 등장한 것 외에는 별것 아닌것 같지만, 1의 보수 방식의 골치꺼리였던 -0 문제와 캐리를 처리해야 하는 문제가 사라진다. 2의 보수 방식에서는 부호를 바꾸려면 비트를 반전한 다음 LSB에 1을 더하면 된다.
3(10) = 0011 >> 1100 + 0001 = 1101 = -3(10)
-6(10) = 1010 >> 0101 + 0001 = 0110 = 6(10)
-0는 아예 없으니 이미 해결됐고, 이제 캐리를 처리하지 않아도 되는지 직접 계산해보자.
2(10) + 3(10) = 0010 + 0011 = 0101 = 5(10)
-2(10) + -3(10) = 1110 + 1101 = 1011 = -5(10) (캐리 발생)
3(10) - 2(10) = 0011 + 1110 = 0001 = 1(10) (캐리 발생)
2(10) - 3(10) = 0010 + 1101 = 1111 = -1(10)
위에서 캐리가 발생했을 때, LSB에 1을 더해주지 않아도 결과가 정확한 것을 확인할 수 있다. 이제 덧셈이든 뺄셈이든 그냥 더하기만 하면 된다. 이제 구현해야 하는 회로가 무척 간단해졌음을 느낄 것이다.
2의 보수 방식의 장점을 요약하면 다음과 같다.
- MSB가 0이면 양수, 1이면 음수라는 성질이 유지된다.
- 음수를 더하는 방식으로 뺄셈을 할 수 있다.
- 음수의 비교연산에서 발생하는 모순이 해결된다.
- 0이 두개나 존재하는 모순이 해결된다.
- 덧셈과 뺄셈을 구현할 때 캐리를 처리하지 않아도 된다.
[출처] 1의 보수, 2의 보수|작성자 드림유
'computer' 카테고리의 다른 글
게임런처를 만들어 봅시다 아이닉스 호두마루님글 (1) | 2013.09.15 |
---|---|
마이크로프로세서(Micro processor) (0) | 2011.01.01 |
RISC와 CISC (0) | 2010.12.21 |
DDoS란? (0) | 2009.07.08 |