_

Always be tactful

개인 학습/CS

[CS] 컴퓨터의 연산 방식 (feat. 1의 보수 & 2의 보수)

funczun 2025. 3. 26. 03:26

들어가기에 앞서,

컴파일이란 무엇인가?

 

 C, C++, Java, Python 같이 우리가 일반적으로 사용하는 프로그래밍 언어를 고급 언어라고 하며, 기계어와 어셈블리어를 저급 언어라고 한다. 가장 쉬운 구분법은 해당 언어가 인간친화적인지 기계친화적인지를 따지는 것이다.

 

 인간친화적인 고급 언어는 우리가 읽고 쓰기 편하지만 이를 그대로 전달한다면 컴퓨터는 이해할 수 없다. 이유를 간단히 설명하자면, 컴퓨터는 전기 신호를 바탕으로 이해하는데 이를 `있다(1)`와 `없다(0)` 정도로만 구분하기 때문이다.

 

 CPU가 직접 해석하고 실행할 수 있도록, 사람이 작성한 고급 언어인 `코드`를 `기계어`로 번역하는 것을 `컴파일`이라고 한다.

소스 코드를 실행 가능한 파일로 만드는 전체 과정을 `빌드`라고 하며, 컴파일은 빌드 과정의 일부인 셈이고, 그 역할은 소스 코드를 기계어로 변환하는 것이다. (단, 컴파일이 없는 빌드도 존재할 수 있다.)

컴퓨터는 음수를 나타낼 수 있을까?

 

 컴퓨터는 0과 1로만 연산을 수행하기 때문에 수를 표현할 때도 이러한 특성이 반영된다. 일단 정수를 표현할 때 이진법을 사용하는데, 당연하게도 `음수`란 개념 자체가 존재하지 않는다. 그래서 음수를 나타낼 땐 `1의 보수`와 `2의 보수`라는 개념이 활용된다.

 

 보수란 `어떤 수에 대해 특정 기준값과 합했을 때 특정 값이 되는 수`다. 쉽게 `보완해 주는 수` 정도로 말할 수 있을 듯하다. 이진수에서 보수의 개념은 크게 두 가지다. 첫 번째는 `감산 보수`이며, 두 번째는 `기수 보수`이다.

  • 감산 보수(1의 보수) → 2^n - 1에서 뺀 값
  • 기수 보수(2의 보수) → 2^n에서 뺀 값

 1의 보수는 각 비트를 반전하여 얻는 값이다. 예를 들어 `5`를 8비트로 표현하면 `0000 0101`이고, 이때 각 비트를 반전시키면 `1111 1010`이 된다. 즉 `5`의 1의 보수는 `1111 1010`인 셈이며, 이것은 `-5`를 표현한 것이 된다.


1의 보수, 문제는 없을까?

 

 1의 보수는 얼핏보면 문제가 없어 보인다. 그러나 이 방식은 덧셈을 수행할 때, 캐리를 고려해야 하는 문제가 발생한다.

 

 말이 다소 어려울 수 있는데 이해를 돕기 위해 `0`을 생각해 보자. 1의 보수에서는 양수와 음수가 서로 보수 관계가 되도록 각 비트를 반전시켜 음수를 표현한다. 즉, 같은 0을 두고 `+0`과 `-0`이 서로 다른 두 개의 형태로 존재하는 문제가 발생한다. (1의 보수 개념 안에서 `+0`은 `0000`이 되고, `-0`은 1111이 된다.)

 

 캐리 보정이란 1의 보수를 사용해 덧셈을 할 때 , 올림수(Carry)를 다시 더해주어야 하는 것을 말한다.

덧셈을 할 때, 자릿수를 넘어서는 값이 발생하면 그 값을 다음 자리로 넘기게 되는데 그것을 `캐리`라고 한다.

 

        ▼ 1의 보수 캐리 보정 과정 ▼        

# 1의 보수

  0000 0101  (5)
+ 1111 1010  (1의 보수로 표현한 -5)
------------
  1111 1111  (결과, 캐리 발생)
`5`와 `-5`를 덧셈한 결과 `1111`이라는 결과가 나오는데, `1111`은 1의 보수에서 `-0`을 나타낸다. 그러나 우리가 생각하는 정상적인 연산 결과는 `0`이다.
# 캐리 보정

  1111 1111  (결과, 캐리 발생)
+ 0000 0001  (캐리 추가)
-------
  0000 0000  (정확한 결과)
덧셈 후 최상위 비트에서 캐리가 발생하였기 때문에, 다시 최하위 비트에 더해주어 해결하였다.

2의 보수의 출현

 

 1의 보수는 직관적이지만 고려해야 할 점이 많다. 고려해야 할 점이 많다는 것은 그만큼 실수할 확률이 높다는 것을 의미한다. 다소 복잡한 연산 과정을 해결하기 위해 나온 것이 `2의 보수`다. 2의 보수는 1의 보수에서 1을 더한 값이다.

# 2의 보수로 전환

  1111 1010  (1의 보수로 표현한 -5)
+         1  (2의 보수로 만들기 위한 1 추가)
------------
  1111 1011  (2의 보수로 표현한 -5)
  0000 0101  (5)
+ 1111 1011  (2의 보수로 표현한 -5)
------------
1 0000 0000  (결과는 9비트이나, 캐리 무시)
캐리를 무시하고 여전히 8비트 기준으로 보면 `0000 0000`이 되며, 이는 우리가 바라던 정상적인 결과 값, `0`이다.

 

 쉽게 설명하면, 기존 1의 보수에서 문제가 되던 `-0`을 지워버려 캐리 문제를 해결한 것이다. 2의 보수에서는 캐리가 발생하더라도 무시하면 된다.

'개인 학습 > CS' 카테고리의 다른 글

[CS] 1.1 + 0.1 != 1.2인 이유  (1) 2024.12.14
[CS] 1.1 + 0.1 != 1.2, Why?  (1) 2024.12.13
[DS] 스택, 큐, 덱  (0) 2024.11.26
[DS] Stack, Queue, Deque  (1) 2024.11.25
[Python] 배열: 인덱스의 시작은 0인가, 1인가?  (8) 2024.11.05