1학년 새내기들한테 컴퓨터 프로그래밍 강의 시간에 2의 보수를 설명하기 위해 고민하다가 써내려간 내용인데, 생각보다 처음 접한 입장에서 이해가 잘된다고 해서 블로그에 남긴다.
이하는 수업시간에 활용하기 위해 작성된 내용.
실습 시간에 비트 연산자를 이해하기 위해 '2의 보수'를 얘기했었죠?
너무 어려워서 이해가 가지 않는다는 분들이 많은 것 같아서 추가적인 설명을 작성해볼게요.
일단, 기본적으로 2의 보수라는 개념은 '음수'를 표현하기 위해 도입된 개념입니다.
컴퓨터가 사용하는 2진수 체제에서는 0 또는 1 밖에 존재하지 않아서 음수를 표현할 수 없습니다.
그래서 제일 앞에 있는 비트를 부호 비트(Sign bit)로 사용해 음수를 표현하는 방법이 제안되었습니다.
[1의 보수]
처음 고안된 방법은 '1의 보수'라는 방법입니다.
단순하게 not 연산을 한 값을 음수로 쓰자는 개념입니다.
예를 들어서 -1을 표현하고 싶다면, 1에 not 연산을 하면 된다는 거죠.
~ 0001 = 1110 = -1
굉장히 심플하게 음수를 표현할 수 있게 됐지만, 문제가 발생합니다.
바로 0에도 음수 양수가 생겨버리는 문제죠. 다들 알다시피 0에는 부호가 없죠? 그래서 그냥 0이 두 개가 돼버리는겁니다.
0000 = +0
1111 = -0
그러므로, 0000 = 1111
[2의 보수가 등장한 계기]
0이 두 개인게 뭐가 문제냐, 시스템은 잘 동작하지 않냐고 생각할 수 있습니다.
하지만, 1 Byte 마다 표현할 수 있는 값 하나를 손실한다는건 데이터가 방대해지면 그 만큼의 많은 손실이 일어난다는 의미가 되죠.
가령 13 MB 크기의 파일은 50Kbits(약 6.25KB)를 그냥 버리는 일입니다.
대기업 데이터센터는 페타바이트를 넘기는데 엄청난 에너지 손실이 되겠죠.
그래서 하나라도 더 표현하기 위해서 '2의 보수'라는 개념이 등장했습니다.
[2의 보수]
단순하게 생각하면 그냥 -0을 없애기 위해서 음수를 표현할 땐 한 칸씩 옮겨서 표현하자는 개념입니다.
-0 => -1
-1 => -2
...
따라서, 1의 보수법에서 -0을 의미했던 1111을 -1로 하자고 약속하게 됩니다. (2의 보수법에 의한 약속)
바로 이 2의 보수법을 비트 연산 수식으로 정리해서, '-x = ~ x + 1' 로 하자고 정의한 것입니다.
[그래서 not 연산은 왜 그래..?]
그러므로 위 수식을 ~ x에 대해 다시 정리하면, ~(not) 연산이 왜 그런 결과 값을 출력하는지 알 수 있습니다.
수식을 ' ~ x = -x - 1 ' 로 정리할 수 있으므로, 다음과 같은 결과가 나타나게 됩니다.
~ 63 = -63 - 1 = -64
~ 1 = -1 - 1 = -2
~ True = -1 - 1 = -2
~ 127 = -127 - 1 = -128
이제 왜 ~(not) 연산의 결과가 직관적이지 않았는지 알 수 있겠죠?