안녕게이들아?
지난 번에 컴퓨터가 덧셈을 하는 법에 대해 알아봤다면 오늘은 뺄셈에 대해 알아보도록 하자.
0. 용어 설명
1의 보수 : 2진수에서 모든 비트를 반전시켜 준 것. (1 -> 0, 0 -> 1)
0. 서론
컴퓨터는 양수와 음수를 어떻게 구분하여 저장할까?
아래 만화를 보며 생각해보자.
32767 마리에서 한 마리를 더 세니까 -32768마리가 되부렀다
ㅍㅌㅊ?
컴퓨터는 음수를 어떻게 표기할까?
컴퓨터가 2진수로 수를 저장한다는 것은 다들 잘 알 것이다.
또한 앞선 덧셈편에서 언급을 하였으니 모르는 게이들도 그 글을 보면 알게될 것이다.
7이라는 수는 2진수로 111이다.
그럼 -7은 어떻게 저장할까?
가장 앞자리에 +인지 -인지 기록하는 비트가 있으면 편할 것이다.
7은 0 111
-7은 1 111
이런식으로...
하지만 이것이 정말 편할까?
인간이 보기엔 편할 지 모르지만, 컴퓨터에겐 그다지 편하지 않을 수도 있다.
(제일 앞의 부호를 보고 케이스를 나눠야 하고, 음수 케이스의 경우 또 다른 과정을 거쳐야 수를 연산에 사용할 수 있기 때문이다)
그래서 또 다른 효율적인 음수 표기법이 필요하게 된다.
1. 1의 보수
보수(Complement)는 각 비트의 값을 반전 시켜주는 것을 의미한다.
예를 들어 1이라는 수의 보수는 0이고, 0이라는 수의 보수는 1이다.
이는 1자리의 비트에만 적용되는 것은 아니고 여러 자리의 비트에도 적용된다.
101의 보수는 010이다.
사실 보수를 구하는 방법은 여러가지가 있는데, 그 중에서도 이것은 1의 보수이다.
보수를 이용하여 음수의 표기를 정의할 수 있다.
숫자 x의 1의 보수를 -x로 정의하는 것이다.
예를 들어 숫자 3 == 0011의 1의 보수인 1100은 -3이 되는 것이다.
(3은 단순히 11로도 적을 수 있지만, 보수 계산을 할 때에는 해당 숫자가 차지하는 메모리의 비트를 전체를 반전시켜야 한다.
여기서는 각 숫자를 4비트 단위라고 보고, 11을 0011로 생각한다.)
4비트(0000~1111)의 수로 -7부터 7까지 표현할 수 있다.
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 -7
1001 -6
1010 -5
1011 -4
1100 -3
1101- 2
1110 -1
1111 -0
이제 앞의 양 세는 만화가 이해가노?
7(0111)의 비트에 1을 더한 1000은 8이 아니라 -7이다.
그런데 여기서 보면 이상한 점이 있다.
바로 -0의 존재.
-0은 대체 무엇인가?
0과 -0은 뭐가 다른가?
사실 두 수는 그냥 같은 0이다.
하지만 1의 보수를 이용하면 0의 1의 보수를 취하면 1111이 나오게 되기 때문에 0의 보수가 0이 아니게 된다.
이러면 4개의 비트로 표현할 수 있는 수가 15개 밖에 되지 않고, -0과 0을 동일하게 인식하는 것을 추가로 구현해야 하기 때문에 비효율적이다.
2. 2의 보수
위의 비효율성과 추가적인 이유 때문에 2의 보수를 사용하게 된다.
1의 보수에 1을 더한 값을 의미한다.
4비트 수 3의 2의 보수 값을 구해보자.
0011 == 3
1100 == 3의 1의 보수
1101 == 3의 2의 보수
3의 2의 보수는 1101이다.
곧, 이 수가 -3을 의미한다.
2의 보수에서는
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 -8
1001 -7
1010 -6
1011 -5
1100 -4
1101 -3
1110 -2
1111 -1
-8부터 7까지의 16가지 수를 표현할 수 있게 된다.
3. 뺄셈
제목엔 분명 컴퓨터가 뺄셈하는 법을 알아보자인데, 보수이야기만 실컷한다.
대체 뺄셈하는 법이랑 보수가 무 슨상 관이라는 것일까?
우리가 10진수의 뺄셈을 하는 것을 생각해보자.
오늘도 일게이 수준에 맞는 뺄셈 하나 가져와봤다 ㅍㅌㅊ?
1의 자리를 계산할 때, 5에서 9를 빼기에는 5가 모자라기 때문에 10의 자리에서 1을 빌려와서, 15에서 9를 빼서 6의 결과를 얻어냈다.
그런데..
765-39라는 것은
사실
765+(1000-39)-1000
와도 같은 것이다.
즉, 765-39는
765+961 = 1726 을 계산한 후에
제일 앞자리의 1(1000)을 빼버린 것과 같은 결과인 것이다.
2진수의 뺄셈도 같다.
12-5를 계산한다고 보자.
01100 == 12
00101 == 5
이 두수를 뺄 때
일단 100000 - 00101을 계산한다.
이 과정은 2의 보수를 구하는 과정과 같다.
모든 비트를 반전시키고 1을 더하는 것.
11010+1 = 11011 == (-5) 가 된다.
01100 == 12
11011 == -5
이 둘을 더해보자.
1 00111
앞에 빨간색으로 표시한 1은 2의 보수를 구할 때 100000을 의미한다.
이제 이 수를 그냥 버리면..
00111 == 7
12 - 5 = 7을 계산 해냈다.
4. 서브트랙터(Subtractor)
그럼 이제 컴퓨터가 뺄셈하는 칩을 보자.
엥? 이거 완전 애더 아니냐?
맞다. 이것은 그냥 덧셈을 해주는 풀애더 4개를 붙여놓은 것이다.
하지만 다음과 같이 A+B 또는 A-B에서 B의 보수도 쓸 수 있게 하면..
MUX는 입력값에 따라 case 0 또는 case 1의 값을 출력해주는 것이다.
지금의 경우 case 0에는 B가 연결되어 있고 case 1에는 B를 반전시킨 값이 연결되어 있으니
(세모에 동그라미가 붙은 것은 inverter라고 하는데, 비트의 값을 반전시켜주는 기능을 한다.)
Add가 아닐 경우 (== Sub일 경우)
즉, 덧셈이 아니거나 뺄셈일 경우 (같은 말이다)에 case 1을 출력하도록 하고, 이와 함께 C0에도 뺄셈일 때 1을 입력하도록 하면,
Adder에 B 자리에 B의 2의 보수의 값을 입력할 수 있게 된다.
즉, 사실 subtractor는 별도의 구현 없이 (약간의 케이스를 분리하는 것은 필요하지만) 입력값을 달리하면 뺄셈의 기능도 구현할 수 있음을 알 수 있다.
이런식으로 B의 입력 자리에 SUBTRACT여부를 B와 XOR 시킨 것을 입력해주면, Full Adder만으로 덧셈과 뺄셈을 모두 할 수 있게 된다.
(x XOR y에서, y의 값이 일정할 때, x가 0이면 그냥 y를 반환하고, x가 1이면 y의 invert된 값을 반환한다. -- xor의 정의를 생각해보면 쉽게 알 수 있다.)
5. 다양한 부호의 뺄셈 경우
(양수) - (양수)의 경우에는 위에서 예를 들었으니 아.. 그런가 보다. 하고 납득이 갈텐데
부호가 다를 경우에는 어떨까?
7과 2의 부호를 서로 다르게 하여 계산을 수행했을 때, 모든 경우에 정확한 결과가 나옴을 알 수 있다.
3줄요약
1. 뺄셈은
2. 보수를 들고 일어난
3. 하나의 폭동이야
출처
url.kr/2oMKPw