금융 경제 보험 정보
C++ 기초공부 - 컴퓨터는 음수를 어떻게 이해할까 본문
1. 컴퓨터는 음수를 어떻게 이해할까?
컴퓨터는 세상의 모든 것을 0과 1으로만 받아들인다. 그럼 컴퓨터는 음수라는 개념을 어떻게 이해할까?
메모리에 데이터가 저장되는 최소 단위는 8비트가 모여있는 1바이트이다. 1바이트에는 0 혹은 1을 나타낼 수 있는 8개의 비트 공간이 있다. 이 8개의 공간 중 가장 첫번째 공간에 0이면 양수, 1이면 음수라고 이해한다.
이 가장 첫번째 공간을 (Most Significant Bit, MSB) 이라고 한다.
그런데 여기서 한 가지 의문이 든다. 10진수의 255를 이진수로 표현을 하면
1, 1, 1, 1, 1, 1, 1, 1 이다.
첫 번째 공간이 1이면 음수라고 하지 않았었나? 그런데 왜 양수인 255가 되지? 바로 두가지의 상황이 존재하기 때문이다. 음수 부호를 사용하는 경우와 사용하지 않는 경우이다.
즉 255의 경우에는 첫 번째 칸이 음수 혹은 양수를 나타내는 MSB로 사용된 것이 아니라 모두 2 진수의 8자리로 사용 된 것이다.
그래서 255처럼 MSB 를 사용하지 않는 8자리 모두 정수의 경우에는 unsigned 로 표시를 해준다. 영어 그대로 부호로 지정하지 않는다고 생각해도 될 듯 하다.
int main(){
unsigned char c = 0;
c = 255;
return 0;
}
여기서 c =255; 의 경우 char 의 자료형을 unsigned 라고 선언하였기 때문에 컴퓨더도 255를 정수 255로 이해한다.
다음으로 음수를 사용 하는 경우에는 signed 라고 자료형에 표시를 해준다.
int main(){
signed char c = 0;
c = 255;
return 0;
}
위의 코드에서는 자료형 char를 부호 표시형 signed라고 선언하였기 때문에 컴퓨터는 255를 255로 이해하지 않는다.
255가 값으로 입력이 되고 나면 십진수 255는 컴퓨터의 메모리에 이진수로 변환이 되어 1,1,1,1,1,1,1,1 으로 입력이 된다. 그럼 컴퓨터는 가장 첫번째 자리의 1을 정수로 생각하지 않고 음의 부호로 이해하게 되고 그 결과 -1 이라는 음수로 이해한다.
2. 2의 보수법
그런데 여기서 잠깐! signed 로 선언하게 되면 가장 첫번째 자리수가 1이기 때문에 -1이라는 것을 알겠는데 왜 1,1,1,1,1,1,1,1을 -1으로 처리할까?
이것을 이해하기 위해서는 먼저 컴퓨터가 덧셈과 뺄셈을 어떻게 하는지 이해해야 한다. 컴퓨터는 기본적으로 결국 1과 0 즉 이진수를 활용한 연산장치이다. 그것이 그냥 계산기 같은 형태이던, 음악을 틀거나, 비디오를 보여주거나, 게임을 하거나 모든 형태의 가장 깊숙한 레벨에서는 결국 모두 1과0의 연산이다.
그래서 컴퓨터는 항상 CPU의 메모리 연산을 가장 효율적으로 할 수 있는 방향으로 발전이 되어 왔다. 연산의 가장 기본이 되는 덧셈의 경우 인간이 하는 자릿수 올림의 형태로 똑같이 진행된다.
그런데 뺄셈의 경우에는 음수의 덧셈이라는 방법을 활용한다. 예를들면 인간의 십진수 뺄셈의 경우에는 1 -1 = 0, 10 - 10 = 0 이다. 그런데 만약 1 + (-1) = 0 , 10 +(-10) =0 으로 계산을 해도 결과 값은 똑같다. 이것또한 뺄셈의 한 방법이라 볼 수 있다.
이런 방식으로 해당 양수를 0으로 만들어주는 값을 찾아서 더해서 0으로 만들어주는 값이 그 해당양수에 상응하는 음수가 되는 것이다.
예를들어보자
십진수 127을 이진수로 바꾸게 되면 01111111 이 된다. 그럼 2진수 덧셈을 하여서 해당 숫자를 0으로 만들려면 어떻게 해야 될까 ?
10000001 을 더해주면 된다.
즉 이진수 01111111 + 10000001 = 0 이 나온다. 각 자리수를 실제로 더하면서 2진수의 맞춰서 각 자리수를 올려주면 마지막 값은 100000000 나오게 되고 8비트 정수에서는 가장 앞 자리 1을 버려줌으로 0이 된다.
01111111
+ 10000001
_______________
100000000
그럼 처음에 01111111 이 십진수로 127이라고 하였다. 그렇기 때문에 십진수 127을 덧셈하여 0으로 만들어줄 수 있는 음수는 -127이 되고, 결국 이진수 10000001 은 -127이다.
바로 이렇게 컴퓨터가 음수를 만드는 방법을 2의 보수(two's complement) 이라고 한다. 2의 보수는 양수 2진수에 상응하는 음수를 찾기 위하여 1) 대응하는 이진수를 반전시킨다. 예를 들어 0은 -> 1로, 1은 ->0으로 만드는 것이다.
그래서 위의 127의 이진수인 01111111를 다시 예로 들어보면
0->1 , 1->0, 1->0, 1->0, 1->0, 1->0, 1->0, 1->0 으로 바꿔준다. 그럼 10000000 이 된다.
1) 그 후에 1을 더해 준다. 1을 더해주는 이유는 1을 더해야 덧셈 연산결과 0으로 딱 맞아 떨어지기 때문이다. 그래서 10000000 에 +1을 하면 10000001 이 된다.
이 처럼 2의 보수란 x를 -X로 바꾸는 과정, 즉 컴퓨터가 음수와 뺄셈을 처리하는 과정이다.
3. 컴퓨터의 음수와 뺄셈을 이해해야 하는 이유
결국 여기서의 핵심은 컴퓨터가 인식하는 정수와 음수의 체계를 이해해서 프로그램을 짜야 한다는 것이다.
int main(){
unsigned char c = 0;
c = 255;
c = -1;
return 0;
}
위의 함수에서 c = 255; 와 c = -1; 은 둘다 그냥 컴퓨터에게는 1,1,1,1,1,1,1,1 똑같은 형태일 뿐이고 MSB가 없기 때문에 그냥 똑같은 255이다.
int main(){
signed char c = 0;
c = 255;
c = -1;
return 0;
}
반대로 이 함수에서 c = 255; 와 c = -1; 은 둘다 역시 그냥 컴퓨터에게는 1,1,1,1,1,1,1,1 똑같은 형태일 뿐이고 MBS가 있기 때문에 그냥 똑같은 -1 이다.
이런 컴퓨터의 연산 과정과 자료형의 선언과 자료형의 종류에 따른 메모리 할당 등을 본질적으로 이해하고 있어야 프로그램을 짤 때, 가장 효율적이고 좋은 코드를 짤 수 있다.