공부

2진수의 음수 표현

강병곤 2024. 2. 21. 01:05

 

비트연산자에 대해  배우면서 ~num2(11111111 11111111 11111111 11110000)이 왜 정수 -16이 되는지 의아했다.

이를 이해하기 위해서는 2진수의 음수가 어떻게 표현되는지 알아야 한다.

 

  • 2진수 음수를 나타내는 첫번째 방법 ~ 부호가 있는 절대치를 이용하는 방법.

: 2진수의 가장 왼쪽 비트(MSB)로 양/음수를 나타내고, 나머지 비트로 수를 나타낸다.

가장 왼쪽 비트(MSB)가 0이면 양수, 1이면 음수를 나타낸다.  

*MSB(Most Significant Bit): 가장 중요한 비트. 가장 왼쪽 비트가 수에 가장 큰 영향을 주므로 가장 중요한 비트가 된다. 

 

예시)

8자리 2진수로 수를 나타낸다고 가정하자.

10진수 15를 2진수로 나타내면, 00001111 이 된다. MSB가 0이기 때문에 이 수는 양수이다.

  MSB 나머지
비트 0 0 0 0 1 1 1 1

 

10진수 -15를 2진수로 나타내면, 10001111 이 된다. MSB가 1이기 때문에 이 수는 음수이다.

  MSB 나머지
비트 1 0 0 0 1 1 1 1

 

참 직관적이고 편하지만, 단점이 있다.

컴퓨터는 부호가 있는 절대치로 나타낸 수를 연산하지 못한다. 15와 -15를 계산해보자.

  2진수 10진수
  0 0 0 0 1 1 1 1 (= 15)
+ 1 0 0 0 1 1 1 1 (= -15)
= 1 0 0 1 1 1 1 0 (= -30)

0이 나와야 하는데 엉뚱한 값이 나와버린다.

 

또, 0을 표현하는 방법이 2가지가 되어버린다.

0은 부호가 있든 없든 0이기 때문에, 00000000 이나 10000000 둘다 0이 된다. 

 

 

  • 2진수 음수를 표현하는 두번째 방법 ~ 1의 보수(1's complement)

: 간단하게 설명하자면, 1의 보수 방법에서 어떤 수의 음수는, 수의 비트를 모두 반전시킨 것이다.

ex) 10진수 15 = 2진수 00001111, 10진수 -15 = 2진수 11110000 

 

0의 음수도 0이므로, 1의 보수에서도 0의 표현방법이 2가지 이다.

ex) 10진수 0 = 00000000, 10진수 -0 = 2진수 11111111

 

이 방법은 얼핏 보면 연산에 문제가 없어보인다.

  2진수 10진수
  0 0 0 0 1 1 1 1 (= 15)
+ 1 1 1 1 0 0 0 0 (= -15)
= 1 1 1 1 1 1 1 1 (= -0)

 

그러나 연산 후에 자릿수가 증가하는 경우(carry가 발생하는 경우) 문제가 생긴다.

ex) 16 + (-15) 의 계산

2진수 10진수
  0 0 0 1 0 0 0 0 (= 16)
+ 1 1 1 1 0 0 0 0 (= -15)
=   1 0 0 0 0 0 0 0 0 (= ??)

 

이렇게 bit 수가 늘어나는 연산의 경우 결과 값에 1을 더해야 정상적인 값을 얻을 수 있다.

 

1의 보수 방법을 사용하면 비트만 반전시켜서 음수 값을 얻을 수 있고, 어느 정도 연산이 가능하지만,

캐리가 발생하는 경우 1을 더해주어야 한다는 단점이 있다. 

 

 

  • 2진수 음수를 표현하는 세번째 방법 ~ 2의 보수(2's complement)

: 간단하게 설명하자면, 2의 보수 방법에서 어떤 수의 음수는, 수의 비트를 모두 반전시킨 것에 1을 더한 것이다.

ex) 10진수 15 = 2진수 00001111,  10진수 -15 = 2진수 11110001

 

0의 음수를 표현하면 11111111 + 1 = 00000000 이 되므로 2의 보수 방법에서 0의 표현방법은 하나가 된다.

 

2의 보수 방법은 연산 과정에서 캐리가 발생하더라도 발생한 캐리값을 그대로 버리면 된다.

2진수 10진수
  0 0 0 1 0 0 0 0 (= 16)
+ 1 1 1 1 0 0 0 1 (= -15)
=   1 0 0 0 0 0 0 0 1 (= 1)

 

컴퓨터는 2의 보수 방법으로 음수를 구한다.

 

 

이제 코드에서 num2 = 15 일때 ~num2 = -16이 되는지 이해할 수 있다.

num2 = 00000000 00000000 00000000 00001111

~num2 = 11111111 11111111 11111111 11110000

~num2의 비트를 반전시키고 1을 더하면 ~num2의 음수가 무엇인지 알 수 있다.

~num2의 비트를 반전시키고 1을 더한 값 = 00000000 00000000 00000000 00010000 //(= 16)

~num2의 음수가 16이니 ~num2는 원래 -16이었을 것이다.