Please enable JavaScript to view the comments powered by Disqus.2의 보수란 무엇인가? 왜 컴퓨터는 2의 보수를 사용할까? what is two’s complements
Search
💹

2의 보수란 무엇인가? 왜 컴퓨터는 2의 보수를 사용할까? what is two’s complements

태그
bit
Algorithm
two complements
Math
공개여부
작성일자
2022/11/02
요즘 Bit 연산의 매력에 빠져들었는데 이 기회에 2의 보수가 뭔지 왜 필요하게 된 것인지 한번 정리해보려고 한다. 2의 보수를 알려면 1의 보수부터 정리해야 한다.
그 전에 우리끼리 한가지 함수를 만들었으면 한다.
fun inverse(number: Int): Int
Kotlin
이 함수는 어떠한 숫자를 받으면 2진수로 반전 시킨다고 가정하자. 내부 구현은 논의하지 않겠다.
예를들어 1101 이 입력되면 출력은 0010 으로 반환된다.

보수

사전적 정의는 네이버 국어사전에서 가져왔다.
수학 각 자리의 숫자의 합이 어느 일정한 수가 되게 하는 수. 예를 들어 10의 7에 대한 보수는 3이다.

1의 보수

1의 보수는 위의 정의로 파악하면 다소 어렵다.
일단 비트를 반전 시킨다고 이해하면 좋다.
임의의 숫자 n 이 있을때 1의 보수는 위에서 정의한 함수 inverse(n) 의 결과가 1의 보수이다.

2의 보수

1의 보수에 + 1을 더하면 나온값이다.

왜 컴퓨터는 2의 보수를 사용할까?

개념 설명

000001012=5100001012=5\begin{aligned} 00000101_{2} &= 5\\ 10000101_{2} &= -5 \end{aligned}
컴퓨터에서 2진수는 00000101 은 십진수로 5 이다.
컴퓨터에서 -5는 10000101 로 앞에 1을 붙이면 -5가 된다.
즉, 가장 첫 번째 자리를 sign bit 라 한다.
그리고 8자리를 사용하니 8 bit 숫자이다.

1의 보수

1의 보수는 다음과 같다. 편리한 설명을 위해 4bit로 작성한다.
10002=710012=610102=510112=411002=311012=211102=111112=000002=000012=100102=200112=301002=401012=501102=601112=7\begin{align} 1000_2 &= -7 \\ 1001_2 & = -6 \\ 1010_2 &= -5 \\ 1011_2 & = -4 \\ 1100_2 &= -3 \\ 1101_2 &= -2 \\ 1110_2 & = -1 \\ 1111_2 &= -0 \\ 0000_{2} &= 0 \\ 0001_2 &= 1 \\ 0010_2 &= 2 \\ 0011_2 & = 3\\ 0100_2 & = 4\\ 0101_2 &= 5 \\ 0110_2 &= 6 \\ 0111_2 &= 7 \end{align}
1.
-1 은 inverse(1) 이다.
2.
-0 이 존재한다.

5+(5)5 + (-5) 의 결과는 어떻게 될까?

0101+10101111\begin{aligned} &0101 \\ +&1010 \\ \hline \\ & 1111 \end{aligned}
5+(5)0\begin{aligned} &5 \\ +(-&5)\\ \hline -&0 \end{aligned}
111121111_2 이고 이 값은 0-0 이다.

5+(2)5 + (-2) 의 결과는 어떻게 될까?

0101+1101(1)0010\begin{aligned} &0101 \\ +& 1101 \\ \hline (1)&0010 \end{aligned}
1이 carriage bit 가 되어 5bit 값이 나온다.
하지만, 4bit 만 연산하기로 했기 때문에 앞의 1은 제외한다.
5+(2)2\begin{aligned} &5 \\ +(-&2)\\ \hline &2 \end{aligned}
2진수 연산을 그대로 10진수로 옮기면 위와 같다.
실제로 5-2 는 3이지만, 1의 보수로 연산하면 2이다.

5+(3)5+(-3)의 결과는 어떻게 될까?

0101+1100(1)0001\begin{aligned} &0101 \\ +& 1100 \\ \hline (1)&0001 \end{aligned}
5+(3)1\begin{aligned} &5 \\ +(-&3)\\ \hline &1 \end{aligned}
동일하게 carriage bit 이 존재하지만 4bit 이므로 무시한다.
000120001_2 는 1의 보수에서 십진수로 1을 의미한다. 실제로는 2 이지만

1의 보수의 연산

5 + (-5) = -0
5 + (-2) = 2
5 + (-3) = 1
각각 1을 더하면 -0 을 제외하고는 실제 10진수의 연산 결과와 같다.
5 + (-5) = -0 + 1 = 1 (very close, not same)
5 + (-2) = 2 + 1 = 3 (same)
5 + (-3) = 1 + 1 = 2 (same)

2의 보수

10002=810012=710102=610112=511002=411012=311102=211112=100002=000012=100102=200112=301002=401012=501102=601112=7\begin{aligned} 1000_2 &= -8 \\ 1001_2 & = -7 \\ 1010_2 &= -6 \\ 1011_2 & = -5 \\ 1100_2 &= -4 \\ 1101_2 &= -3 \\ 1110_2 & = -2 \\ 1111_2 &= -1 \\ 0000_{2} &= 0 \\ 0001_2 &= 1 \\ 0010_2 &= 2 \\ 0011_2 & = 3\\ 0100_2 & = 4\\ 0101_2 &= 5 \\ 0110_2 &= 6 \\ 0111_2 &= 7 \end{aligned}
1.
-0은 존재하지 않는다.
2.
1의 보수 + 1

5+(5)5 + (-5) 의 결과는 어떻게 될까?

0101+10110000\begin{aligned} &0101 \\ +&1011 \\ \hline \\ & 0000 \end{aligned}
5+(5)0\begin{aligned} &5 \\ +(-&5)\\ \hline &0 \end{aligned}
이진수로 000020000_2 이고 이 10진수 값은 00 이다.

5+(2)5 + (-2) 의 결과는 어떻게 될까?

0101+1110(1)0011\begin{aligned} &0101 \\ +& 1110 \\ \hline (1)&0011 \end{aligned}
1이 carriage bit 가 되어 5bit 값이 나온다.
하지만, 4bit 만 연산하기로 했기 때문에 앞의 1은 제외한다.
001120011_2 는 10진수로 3이다.
5+(2)3\begin{aligned} &5 \\ +(-&2)\\ \hline &3 \end{aligned}
5-3 은 의심의 여지없이 3이다.

5+(3)5+(-3)의 결과는 어떻게 될까?

0101+1101(1)0010\begin{aligned} &0101 \\ +& 1101 \\ \hline (1)&0010 \end{aligned}
1이 carriage bit 가 되어 5bit 값이 나온다.
하지만, 4bit 만 연산하기로 했기 때문에 앞의 1은 제외한다.
001020010_2 는 십진수로 계산하면 2 이다.
5+(3)2\begin{aligned} &5 \\ +(-&3)\\ \hline &2 \end{aligned}
5-3은 2이다.
이렇게 계산해보면 오차 없이 가장 정확한 연산이 2의 보수가 된다. 따라서 컴퓨터는 양수, 음수의 연산의 오차를 제거하기 위해 2의 보수를 사용하는 것이 더욱 타당해진다.
함께 읽어보면 좋은 글