C언어에서 정수는 어떻게 표현이 될까요? 결론부터 말하자면, 2의 보수 표현법으로 표시합니다. 그러면 이 표기법이 무엇일까요? 4bit로만 표현되는 정수 데이터가 있다고 해 봅시다. 부호가 있는 정수인 경우, 최상위 비트는 보통 부호를 표시합니다.

 

 

 

 이 때 signed bit가 1이면 음수를, 아니라면 양수를 나타냅니다. 만약에 부호 없는 정수형이라면, 4bit를 다 쓰겠지요. 4개의 비트로 표현할 수 있는 상태값은 16개입니다. 수로 따지면 0부터 2^4-1까지입니다. 그런데 하나의 비트를 부호를 위해서 썼으니, 일단 양수에 대해서, 0, 1, 2, 3, 4, 5, 6, 7까지면 표현이 가능하겠군요.

 

 

 

 이것들은 각각 2진수로 0부터 7까지를 나타냅니다. 음수일 때가 문제인데요. 이것을 어떻게 표현하면 좋을까요?

 

 


 1의 보수란, 각 자릿수를 더했을 때, 1이 되는 수를 말합니다. 예를 들어서 2진수 0111의 1에 대한 보수는 1000이고, 0100의 1의 보수는 1011입니다.

 

 

 그러면, 2진수 a에 대한 1의 보수 값을 (-a)로 취하면 되지 않을까요? 그러면, 1000이 -7이 되고, 1001이 -6, ... 1111이 -0이 될 겁니다. 이 부분은 사실 크게 문제가 없어 보입니다. 4bit로 표현되는 구간 [-7, 7]에 속하는 정수들 중에서 a + (-a)의 값이 0이기 때문입니다.

 

 그런데 0과 -0이 있어요. 이 두 값은 같은데, 0을 표현하기 위해서 0000을, -0을 표현하기 위해서 1111을 쓰고 있어요. 이렇게 하면 뭔가 문제가 생기지 않을까요? 크기가 작은 -7부터 -6, ... ,-0, 0, ... , 7까지 증가하는 순서대로 다시 그림을 그려보겠습니다.

 

 

 그러면 이런 시나리오를 생각해 봅시다. 1110에 0010을 더하면 무슨 값이 나와야 하나요? 그림에 따르면 1110은 0001을 단순히 비트 반전한 것이기 때문에 -1입니다. 그리고 0010은 2입니다. -1에 2를 더하면 1이 나와야 합니다. 상식적으로는 그러합니다.

 

 그런데 실제로 1110에 0010을 더하면 10000이 나오고, 여기서 하위 4비트만 취하기 때문에 0000이 나옵니다. 왜 이런 결과가 나왔을까요? 이는, -0이 있었기 때문입니다.

 

 

 

 화살표 방향으로 1칸 가면 1이 더해집니다. -1에서 1칸 가니까 -0이 있었습니다. 이것은 결과가 제대로 나옵니다. 그런데 -0에서 1칸 또 오른쪽으로 가면 어떤가요?

 

 

 -0에 1을 더하면 1이 나와야 하는데 0이 나왔어요. 이러면 꽤 복잡해 집니다. 즉, -0과 0이 있었고, -0에 1을 더하면 0이 나왔기 때문에, 그냥 일반적인 2진수 덧셈으로 더해서, 올바른 결과가 나오지 않았던 것입니다. number system에서 0이 연속으로 2번 나오지 않는다는 게 핵심입니다. 그러면, 이러한 문제를 어떻게 해결하면 좋을까요?

 

 


 노란 부분 때문에 2진수의 1의 보수 표현법이 문제가 되었습니다.

 

 

 그러면 노랗게 칠한 카드에 1을 추가로 빼는 건 어떨까요?

 

 

 이러면 뭔가 자연스러워 지는 것을 볼 수 있어요. -8 다음에 -7 이 오고, -1 다음에 0 이 오고, 0 다음에 1이 오고.

 

 

 -7은 1001로 표현이 됩니다. 7은 0111로 표현이 됩니다. 그러면 이 두 이진수를 더한 값은 얼마나 나올까요? 1001에 0111을 더하면, 10000이 나옵니다. 즉 2^4가 나오는데, 이 때 4는 제가 사용한 bit 수를 의미합니다. 또 다른 거 해 봅시다. -2는 1110으로 표현이 될 겁니다. 2는 0010으로 표현이 되나요? 이 둘을 더하면 10000이 나옵니다. 이게 무슨 관계가 있을까요?

 

 사실 a에서 b를 뺀다는 말은 a에서 (-b)를 더한다는 말과 같습니다.

 

 

 -8이 -7을 잇고, -7이 -6을 잇고, ..., 6이 7을 잇습니다. 저 숫자 카드들은 16개의 화살표로 연결이 되어 있을 겁니다. 그러면, a가 양수일 때, 어떠한 수에서 t를 더한다는 것은, t번 화살표를 탄다는 것이고, t를 뺀다는 것은 t만큼 뒤로 간다는 소리입니다. 단, t는 [0, 16] 범위 내에 있는 정수이고, a는 [-8. 7] 범위 안에 있는 정수라고 했을 때요.

 

 그런데, t를 뺀다고 생각해 봅시다. 예를 들어, 2에서 3만큼 뺀다고 해 봅시다.

 

 

 그러면 3칸만큼 뒤로 간다는 것인데요. 이는 13칸 앞으로 간 것과 같아요. 3에서 13을 보충하면 16, 그러니까 2^4가 나오게 됩니다. 그러면, 13이 2진수로 어떻게 표현이 되나요? 1101로 표현이 됩니다. 그런데, 이것은 부호가 있는 4bit 정수에서 -3을 나타냅니다. 어? 이렇게 보니까 신기하군요.

 

 다른 예제. 저는 0에서 2를 빼고자 합니다.

 

 

 그러면 이 시스템에서는 2를 빼는 게, 즉 (-2)를 더하는 것이, 0에서 14만큼 더하는 것과 같습니다. 더 정확히 말하면, 제가 있는 보라색 위치부터 14번 정방향 화살표를 타는 것과 같아요. 14를 2진수로 표현하면 어떻게 되나요. 1110이 됩니다. 그런데 이것은 4bit system에서 -2를 표현한 것과 같아요. 뭔가 계기판 시스템 같아요. 실제로 그렇게 이해하시면 조금 더 쉽습니다.

 

 


 그러면, 4bit로 표현된 정수를 어떻게 2의 보수로 바꾸는지 봅시다. 2를 예로 들어봅시다.

 

 

 2는 2진수로 0010으로 표현이 됩니다. 이것을 모두 비트 반전 시켜 봅시다.

 

 

 그런데 실제로, 이것은 2의 보수표현법으로 표현하면 -2가 아닌 -3이라고 했어요. 따라서 여기서 1을 더해야 합니다.

 

 

 1110이 나오네요. 즉, 모든 비트를 반전시키고 0001을 더하면 된다는 것을 알 수 있어요. 1110이랑 0010을 더하면 16이 나온다는 것 또한 알 수 있어요. 그러면 거꾸로는 어떻게 바꿀까요? 똑같습니다. 모든 비트를 반전시켜 봅시다.

 

 

 

 

 1110에 0001을 더하면 1111이 나옵니다. 이것은 1110에 대한 1의 보수입니다. 1110에 어떠한 2진수를 더해서 10000이 나오려면, 이 결과값에 1을 더해야 합니다. 그런가요? 따라서 결과값에 0001을 더합니다.

 

 

 짜잔~ 4bit 시스템에서 2진수로 2는 이렇게 표현이 됩니다.

 

 


 내용이 다소 많았습니다. 간단하게 정리해 봅시다. 2진수에서 1의 보수는 0과 -0이 둘 다 있다고 했어요. 이러한 것 때문에, 2의 보수를 쓰는데요. 어떠한 2진수를 2's complement로 만드는 방법은 비트를 모두 뒤집고 1을 더하면 되더라. 이 정도만 기억하시면 좋겠습니다.