int 의 최대 크기는 2,137,483,647

약 21억 이다.

 

여기에 1을 더하면 어떻게 될까?

 

int a = 2,137,483,647;
cout << a++ << endl;

-2,137,483,647 이 된다.

 

 


컴퓨터가 음수를 표현하는 방법을 알아보자.

 

내가 CPU 아키텍쳐라면 음수를 어떻게 표현할까?

 

맨 앞 부호를 (양/음) 부호로 두고

 

0111 은 7 

1111 은 -7

 

이라고 하면 편할것이다.

 

그러나 몇가지 문제점이 있다.

 

  • 0을 나타내는 방식이 2개이다
    • 0000 도 0 이고 , 1000 도 0이 된다.
  • 앞의 부호 비트를 보고 뺄셈을 수행해야한다
    • 0001 과 1001 을 더한다면 원래는 1010 으로 나올텐데 1001이 사실 -1 이므로 덧셈이 아닌 뺄셈을 해줘야한다.

물론 부호 비트를 도입해서 음수와 양수를 구분하는 아이디어 자체는 나쁜 생각은 아니다.

 

int 와 같은 정수 데이터와 다르게 double 이나 float 처럼 소수인 데이터를 다루는 방식에서는 (부동 소수점 표현)

부호 비트를 도입하여서 음수인지 양수인지를 표현한다.

*실제로 부동 소수점 표현법에서는 -0 과 +0 이 있다.

 

하지만 적어도 정수를 표현하는 방식에서는 부호 비트를 사용하는 방식은 문제점이 다분해 보인다.

 

 


[ 2의 보수 ( 2's complement) 표현 ]

 

만약에 어떤  와 해당 수의 음수 표현인 - 를 더하면 당연히도 0 이 나와야 한다. 

0111(2) // 7

여기에 더해서 0000 이 되는 이진수가 있을까? 이 때 덧셈 시에 컴퓨터가 4 비트만 기억한다고 가정해야 한다.

그렇다면 -7 의 이진수 표현으로 가장 적당한 수는 바로 1001 이 될 것이다.

왜냐하면 0111  1001 을 그냥 더하기만 하면 10000 이 되는데, CPU 가 4 비트만 기억하므로 맨 앞에 1 은 버려져서 그냥 0000 이 되기 때문이다.

 

이렇게 덧셈을 고려하였을 때 가장 자연스러운 방법으로 음수를 표현하는 방법을 2의 보수 표현이라고 한다.

 

-7 을 나타내기 위해서는, 7 의 이진수 표현인 0111 의 비트를 모두 반전시키면 1000 이 되는데 여기다 1 을 더해서 1001 로 표현하면 된다.

반대로 -7 에서 7 로 가고 싶다면 1001 의 부호를 모두 반전 시킨뒤 (0110) 다시 1 을 더하면 양수인 7 (0111) 이 나오게 된다.

 

이 체계에서 중요한 점은 0000 의 2 의 보수는 그대로 0000 이 된다는 점이다.

왜냐하면 0000 을 반전하면 1111 이 되는데, 다시 1 을 더하면 0000 이 되기 때문이다.

 

또한 어떤 수가 음수 인지 양수인지 판단하는 방법도 동일하다.

그냥 맨 앞 비트가 부호 비트라고 생각하면 된다.

예를 들어서 1101 의 경우 맨 앞 비트가 1 이기 때문에 음수 이다.

따라서 이 수가 어떤 값인지 알고싶다면 보수를 구한 뒤에 (1101 --> 0010 --> 0011) - 만 붙여주면 된다.

 0011 이 3 이므로, 1101 의 경우 -3 이 됩니다.

 

이와 같이 2 의 보수 표현법을 통해서

  • 음수나 양수 사이 덧셈 시에 굳이 부호를 고려하지 않고 덧셈을 수행해도 되고
  • 맨 앞 비트를 사용해서 부호를 빠르게 알아낼 수 있다는 장점이 있다.

 

한 가지 재미있는 점은 2 의 보수 표현법에서 음수를 한 개더 표현할 수 있다.

왜냐하면 1000 의 경우 음수 이지만 변환 시켜도 다시 1000 이 나오기 때문이다. (1000 --> 0111 --> 1000)

실제로 int 의 범위를 살펴보면 -2,147,483,648 부터 2,147,483,647 까지 . 음수가 1 개 더 많다.

'Language & etc > etc' 카테고리의 다른 글

Window 에서 Magic Trackpad 사용하는법  (0) 2022.03.21

+ Recent posts