DEV Community

loading...

2의 보수, 컴퓨터가 음수를 표현하는 방법

Jinseok
・1 min read

우리는 숫자 앞에 - 기호를 표시함으로 쉽게 음수를 표현할 수 있다. 하지만 0과 1뿐인 컴퓨터에선 어떻게 표현할 수 있을까?

음수인지 양수인지 구별하기 위한 부호 비트를 살펴보고 단점을 보완하기 위한 1의 보수와 2의 보수를 살펴봤다.

☀︎ (2)는 2진수를 의미함


부호 비트

sign bit

가장 왼쪽의 비트MSB를 부호로 사용해 음수를 표현하는 방식이다. 0(2)이면 양수, 1(2)이면 음수임을 뜻한다. 4비트 시스템을 예로 들었을 때 0010(2)은 2이고 1010(2)는 -2이 된다.

숫자를 표현하기 위한 비트가 하나 줄었다는 단점이 있다. C언어에서 unsigned가 붙은 자료형이 붙지 않은 자료형에 비해 월등히 큰 숫자를 사용할 수 있는 게 그 이유다.

그런데 다른 문제가 생겼다. 부호를 사용했을 때 0010(2) + 1010(2)의 결과는 무엇일까? 0이 돼야 한다. 하지만 1100(2)으로 -4라는 결괏값이 나온다.

그럼 0(2)일 땐 더하고 1(2)일 땐 빼면 안 될까? 생각할 수 있다. 그럼 부호 비트가 0(2)일 때와 1(2)일 때 각각 다른 회로를 사용해야 하는데, 단순하게 생각해 보면 덧셈이라는 행위가 2배로 복잡해진다.


1의 보수

one's complement

그런데 누군가 기발한 생각을 했다. 각 비트를 뒤집으면(0(2)은 1(2)이 되고 1(2)은 0(2)이 됨) 단순하게 구현할 수 있는 것이다.

2를 예로 들어보면 0010(2)을 뒤집어 1101(2)로 -2를 표현할 수 있다. 둘을 더하면 1111(2)로 숫자 비트만 뒤집으면 000(2)이 되므로 0이라는 결과를 확인할 수 있다.​

0은 0인데 부호 비트가 1이니 -0이라는 의미심장한 숫자가 등장하게 된다. 게다가 덧셈이 이상한 경우도 등장한다. 0010(2)와 1110(2)를 더하면 2 + -1이므로 1이라는 결과가 나와야 하는데 0000(2), 즉 0이라는 결과가 나온다.

이 문제를 해결하기 위해선 MSB에서 올림이 발생했을 때 가장 오른쪽 비트LSB로 전달해 주는 순환 올림end-around carry이 필요하다.​


2의 보수

two's complement

이제 음수 표현의 최최최종 버전인 2의 보수가 등장한다. 1의 보수처럼 뒤집되 +1(2)을 해준다. -2를 표현하고 싶다면 0010(2)을 뒤집어 1101(2)로 만들고, 여기서 1(2)을 더하면 1110(2)이 된다.

계산해보면 -0이라는 숫자가 없어진다. 1의 보수에선 1111(2)은 -0이었지만 2의 보수에선 000(2) + 1(2)과 같은 효과로 001(2), 즉 -1이 된다.​

그럼으로 음수 숫자를 하나 더 표현할 수 있다. 4비트를 예로 들면 가장 큰 값은 0111(2)인 7이 되고, 가장 작은 값은 1111(2)로 -8이 된다.

게다가 순환 올림도 필요 없기 때문에 음수를 더했을 때도 문제가 없다(하나하나 직접 계산해보면 그 신기함을 경험할 수 있다).


🙌 1, 2의 의미는 무엇일까?

1비트를 예로 들었을 때, 1(2)을 1의 보수 취한다는 것은 1(2) - 1(2)와 같다. 2의 보수를 취한다는 것은 10(2) - 1(2)으로 비트 단위가 달라지는 걸 확인할 수 있다.

여기서 1(2)은 1(10)이고 10(2)은 2(10)인데, 이 모양을 본떠 이름을 지었다고 볼 수 있다.

변환

만약 8비트 시스템에서 부호 있는 정수를 나타낸 11111011(2)라는 숫자를 보게 되면 10진수로 어떻게 표현할 수 있을까?

100000000(2) - 11111011(2) = 101(2) 여기서 부호 비트가 1이니 결과는 -5가 된다.

Discussion (0)