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 |
---|