Search

2의 보수(two’s complement)

Last update: @12/1/2022

컴퓨터의 음수 표현

부호-크기 표현(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의 보수가 됨(two’s complement)
보수로 어떻게 뺄셈을 한다는 것일까? 원래 뺄 수를 취소 하고 오히려 그 수의 보수를 더한다는 개념으로 접근하면 직관적으로 이해할 수 있음
우리에게 익숙한 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을 날려주면 정답 4가 됨
위에서는 보수의 기준값을 10으로 잡았지만 기준값을 100, 1000, … 등으로 정해서 2의 보수를 98, 998, … 등으로 놓아도 원리는 같음. 결과물만 104, 1004, … 등으로 변할 뿐, 맨 앞의 1을 날려주면 정답인 4가 그대로 남게됨
정답이 음수인 경우: 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)가 됨. 따라서 결괏값 6의 보수인 4를 구해서 부호를 바꿔주면 원래 정답을 구할 수 있음
하지만 정답이 양수/음수인 조건에 따라 추가적인 작업이 필요해보이는 건 아직 뭔가 불편한 구석이 있음
그렇다면 이렇게 정답이 양수일 때 맨 앞자리 수가 버려지거나, 정답이 음수일 때 결괏값의 보수를 구하는 것이 어떻게 처리된다는 걸까? 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)을 만든 후 0b1을 더하면 0b1111
여러 포스트에서 -8이라는 수를 하나 더 표현하기 위해 첫번째 비트가 1인 음수에 대해 1씩 더해줬다는 설명을 보았는데, 불필요한 개념이 하나 더 끼어들어가서 ‘어떻게 별개의 개념들이 맞아 떨어져서 보수로 뺄셈을 하는거지?’라는 혼동만 주는 설명이라고 생각함. 첫번째 비트가 부호비트라는 개념을 버리고 단순히 2의 보수를 구했다고 생각하면 됨
0b0111(7)에서 0b0011(3)을 빼는 경우 → 나와야 할 정답 0b0100(4)
*** 0b10000(16)을 기준으로 한 이진수 0b0010(2)에 대한 2의 보수는 0b1110(14)임. 보수라는 것은 자릿수를 기준으로 하기 때문에 같은 수에 대한 보수도 진법마다 다름. 따라서 십진수로 변환해서 생각하면 헷갈릴 수 있음 *** 0 111 +1 101 (0010의 보수) ------ 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

관련 문서