Search

2의 보수(two’s complement)

Created:
Last update:

컴퓨터의 음수 표현

컴퓨터에서 음수를 표현하는 대표적인 두 가지 방식이 있다.

부호-크기 표현(Signed-magnitude representation)

부동 소수점의 음수를 표현하는 가장 보편적인 방식(IEEE floating point)
0과 1로 이루어진 컴퓨터에서 음수를 표현하기 위해서 맨 앞 비트(Most Significant Bit, MSB)를 부호 대신 사용하는 방법. 0이면 양수, 1이면 음수, 뒤의 숫자가 절댓값을 나타낸다.
이 방법은 알아보기도 쉽고 생성하기도 쉽지만 산술 연산이나 음수 비교 연산이 어려워진다.
예를 들어 4비트 컴퓨터에서 10진법 계산 2 - 2를 위해 이진법 0010(2)_{(2)} + 1010(2)_{(2)}을 계산하면 1100(2)_{(2)}이 나오고 이는 -4라는 엉뚱한 숫자가 됨. 이를 해결하기 위해선 회로를 추가 구성해야 하는 등 쉽지 않은 일이다.

2의 보수(Two’s complement)

음의 정수를 표현하는 가장 보편적인 방식. 아래에 설명한다.

보수란?

보충하는 수를 의미한다.

N진법에 대해서 N-1의 보수

: 같은 자릿수에서 가장 큰 값이 되기 위해 필요한 수 ex> 10진수 33의 9의 보수(10-1의 보수): 두자리수에서 가장 큰 값 99가 되기 위해 99 - 33 = 66

N진법에 대해서 N의 보수

: 자릿수를 한 자리 늘리기 위해 필요한 가장 작은 수. N-1의 보수에 1을 더해주면 된다. ex> 10진수 33의 10의 보수: 세자리수 100이 되기 위해 100 - 33 = 67

1의 보수(one’s complement)

위의 N-1의 보수에서 본 것처럼, 2진수에서 1의 보수(2-1의 보수)란 어떤 이진수의 자릿수를 유지한 채 가장 큰 수를 만들어주는 수를 말한다.. 가장 큰 수는 1로만 가득 찬 경우가 됨(10진법의 경우 9로만 가득 찬 경우)
예를 들어 0010(2)_{(2)}이 자릿수가 같은 가장 큰 수 1111(2)_{(2)}이 되려면 1101(2)_{(2)}을 더해줘야하는 것을 알 수 있음. 이 때 1101(2)_{(2)}0010(2)_{(2)}의 1의 보수가 된다.
1101(2)_{(2)}을 구하려면
0010(2)_{(2)}의 1과 0을 반전시키거나
1111(2)_{(2)}에서 0010(2)_{(2)}을 빼는 두 가지 방법이 있다.
컴퓨터 입장에서는 단순히 모든 자리를 반전시키는 방법이 쉽고 빠르다.
1의 보수를 음수로 사용하는 컴퓨터는 매우 드물기 때문에 계산법은 몰라도 무방하다.

2의 보수(two’s complement)

위의 예제에서 본 것처럼 2의 보수와 1의 보수는 1만큼 차이가 남. 따라서 단순히 1의 보수에 1을 더해주면 2의 보수가 된다.
보수로 어떻게 뺄셈을 한다는 것일까? 원래 뺄 수를 취소 하고 오히려 빼려던 수의 보수를 더한다는 개념으로 접근하면 직관적으로 이해할 수 있다.

10진법 예시

우리에게 익숙한 10진법 예시로 개념을 잡아보자
결괏값이 양수인 경우: 7에서 3을 빼는 경우 → 4
7 - 3 = 4 위 식에서 3을 뺀 것을 취소하면 7 - 3 + 3 = 4 + 3 7 = 4 + 3 <- 정답에 3을 더한 효과 위 식에서 3에 대한 10의 보수인 7을 더하면 7 + 7 = 4 + (3 + 7) <- 정답에 10을 더한 효과 7 + 7 = 14
Plain Text
복사
즉, 3을 빼는 대신 3에 대한 10의보수를 더한다는 말은 3을 빼는 것을 취소하고(+3), 3의 보수인 7을 더한다(+7)는 의미다. 즉, 그냥 10을 더해준다는 말이다. 따라서 이번 예제처럼 정답(4)이 양수인 경우, 최종 계산 결과물인 14에서 앞의 1을 날려주면(10을 빼주면) 정답 4가 된다.
여기는 기존 값과 빼는 값 모두 한 자리수를 썼지만, 기존 값이 두자릿 수라면 100의 보수를 사용한 후 마지막에 100을 빼주면 된다.
결괏값이 음수인 경우: 2에서 6을 빼는 경우 → -4
2 - 6 = -4 위 식에서 6을 뺀 것을 취소하면 2 - 6 + 6 = -4 + 6 2 = -4 + 6 <- 정답에 6을 더한 효과 위 식에서 6에 대한 10의 보수인 4를 더하면 2 + 4 = -4 + (6 + 4) <- 정답에 10을 더한 효과 2 + 4 = 6
Plain Text
복사
이렇게 결괏값(-4)이 음수인 경우, 빼야할 6을 취소하고 오히려 4를 더하면 원래 결괏값에 보수의 기준값인 10을 더한 결과와 같아진다.
보수의 기준값인 10을 더했을 때 최종 계산 결괏값(6)이 원래 결괏값(-4)의 절댓값(4)의 보수(6)가 됨. 4의 보수를 -4로 취급하기로 했으므로, 4의 보수인 6은 -4와 같다.

2진법 예시

뺄셈의 결괏값이 양수일 때 맨 앞자리 수가 버려지는게 어떻게 처리된다는 걸까? 결괏값이 양수인지 음수인지를 따로 판별한다는 것인가?
4비트 컴퓨터를 가정하고, 위 예시를 2진법으로 계산해보자
먼저, 뒤의 3개 비트를 이용해 0부터 7까지 8개의 양수를 표현하고, 각 양수에 대한 음수는 2의 보수를 표현형으로 사용하기로 한다.
십진수
이진수
십진수 (표현형)
이진수(표현형)
십진수(실제)
0
0 000
1
0 001
-1
1 111
15
2
0 010
-2
1 110
14
3
0 011
-3
1 101
13
4
0 100
-4
1 100
12
5
0 101
-5
1 011
11
6
0 110
-6
1 010
10
7
0 111
-7
1 001
9
-8
1 000
8
2의 보수를 구하는 법은 모든 자리를 반전시켜 1의 보수로 만들어준 후 1을 더해주면 쉽게 구해진다.
(이하, 이진법 앞에는 0b를 병기하고 이해를 돕기 위해 뒤 괄호 안에 십진법을 병기함)
예를 들어 0b0001(1)을 반전시켜 0b1110(-2)을 만든 후 1을 더하면 0b1111
다른 여러 블로그 포스트에서 -8이라는 수를 하나 더 표현하기 위해 0의 음수를 8로 정했다는 설명을 보았는데, 불필요한 개념이 하나 더 끼어들어가서 ‘어떻게 별개의 개념들이 맞아 떨어져서 보수로 뺄셈을 하는거지?’라는 혼동만 주는 설명이라고 생각한다. 첫번째 비트가 부호비트라는 개념을 버리고 단순히 2의 보수를 구했다고 생각하면 된다.
0b0111(7)에서 0b0011(3)을 빼는 경우 → 나와야 할 정답 0b0100(4)
*** 0b10000(16)을 기준으로 한 이진수 0b0011(3)에 대한 2의 보수는 0b1101(13)이다. 보수라는 것은 자릿수를 기준으로 하기 때문에 같은 수에 대한 보수도 진법마다 다르다. 따라서 계산 중 십진수로 변환해서 생각하면 헷갈릴 수 있음을 주의해야 한다. *** 0 111 +1 101 (0011의 보수) ------ 10 100 (맨 왼쪽 1은 범위를 벗어나 사라짐) 0 100 (결괏값)
Plain Text
복사
0b0011(3)을 빼는 것을 취소하고 보수 0b1101(13)을 더해줬더니 원래 정답 0b0100에 0b10000(16)을 더한 것과 같은 0b10100이 결과로 나온다.
4비트 컴퓨터이기 때문에 범위를 벗어난 첫번째 비트는 자동으로 사라지고 정답만 남음. 즉, 0b10000(16)을 빼준 셈이 되면서 맨 앞의 1이 날아간다.
0b0010(2)에서 0b0110(6)을 빼는 경우 → 현실 세계의 정답은 0b-0100(-4)이기 때문에 컴퓨터 내부의 정답은 0b0100(4)의 음수 표현인 0b1100이 나와야 한다.
0 010 +1 010 (0110의 보수) ------ 1 100 (결괏값)
Plain Text
복사
0b0110(6)을 빼는 걸 취소하고 오히려 2의 보수 0b1010(10)을 더해줬더니 원래 정답 0b-0100(-4)에 0b10000(16)을 더해준 것과 같은 효과가 난다.
따라서 0b1010(4)의 보수인 0b1100이 결과로 나타남. 원래 정답 0b-0100(-4)의 절댓값인 4의 보수임. 애초에 음수는 양수의 2의 보수를 표현형으로 하기로 했으니 이 결괏값을 그대로 저장하면 된다.

기타

2의 보수는 존 폰 노이만이 제안한 방식이다.

References

관련 문서