Electrical engineering

디지털공학/Chap 1.

Chap 1. 디지털 시스템과 2진수 (3) . Digital Systems and Binary Numbers

在夏 2022. 1. 7. 18:11
728x90

1-5. 수의 보수 (complement)

 

자, 앞의 내용들도 처음 배우는 사람들에게는 낯설어서 단순한 변환과정 자체도 머리아프고 귀찮은 작업이였는데, 더더욱 낯선 개념인 보수 (complement)라는 개념이 등장한다.

 

일단 이 낯선 보수 (complement)를 왜 사용할까?

 

결론부터 말하자면, 컴퓨터 하드웨어의 시스템에서 뺄셈을 수행하기 쉽도록 사용하는 것이다. 

(쉽게 사용하려고 만든건데 오히려 사람에겐 납득하기 엄청 어렵다 ㅡㅡ)

이 멍청한 컴퓨터라는 녀석이 어떻게 뺄셈을 하길래 이런 개념을 사용하는지,,,, 보수의 개념부터 천천히 짚어보자.

 

보수에는 두가지 종류의 보수가 있는데

 

1. 감소된 기수 보수 : 기수 r인 n자리의 숫자 N이 주어졌을 때, N에 대한 (r-1)의 보수. 

2. 기수보수 : 기수 r인 n자리의 숫자 N (N≠0)에 대한 r의 보수.

예를 들어 10진수의 경우 r = 10, r-1 = 9이므로 특정 수 N에 대한 한자리 감소된 기수보수를 구할 수 있고 -1을 하지 않는다면 그냥 기수보수를 구한 것이라는 뜻이다.

 

???????

 

언제나 그렇듯. 내가 정하지 않고 다른 똑똑하신 분들이 약속하고 정해놓은 정의에 대해서 배울 때는 항상 난감하다.

'이게 도대체 뭐지??' 라는 생각과 '이걸 왜 알아야 하지??' 라는 생각이 동시에 드는건 어쩔 수 없나보다.

나도 처음에 이 개념을 봤을 때. '보수면 그냥 기수보수지 감소된건 또 뭐고 보수는 또 왜 뺼셈할때 필요해..?'라는 생각에 머리가 띵 했다.

 

그렇다면 조금이라도 더 와닿을 수 있는. 그냥 구하는 공식부터 보도록 하자.

 

기수 r인 n자리의 숫자 N에서.

1. 감소된 기수 보수 : 

2. 기수 보수 :

아. 조금 편안해졌다. 일단 이 식을 보고 풀 줄 안다면 감소된 기수보수든 그냥 기수보수든지 구할수는 있으니까!

 

예를 들어보자. (4125)10 의 경우. r = 10 , r-1 = 9, N = 4125 이므로. 감소된 기수보수는 9의보수이고 기수보수는 10의보수이다. 이대로 위의 공식에 넣어서 풀면 된다.

(지금은 말이 어색할지라도 그냥 9가나왔으니 N에대한 9의보수, 10이 나왔으니 N에대한 10의 보수라는 것이다.)

 

먼저 '감소된 기수 보수' 를 구하는 과정을 보겠다.

 

다른 예시에서 숫자로 풀어보자면.

 

546700 에 대한 9의 보수는 999999 - 546700 = 453299

012398 에 대한 9의 보수는 999999 - 012398 = 987601 (자릿수는 지켜준다)

 

이렇게 계산을 하고 있자면, 우리 눈에 들어오는 패턴이 보인다. 바로 999999로 이루어진 수이다. 

이는 감소된 기수보수의 정의에서 주어진 수가 decimal number 숫자이고, 그 수의 자릿수만큼 10에 제곱하여 1만큼 뺀 결과이기 때문이다. 

 

그렇다면 2진수의 경우에선 r = 2이므로 정의에 의해서

이 정의에 의하면 2^n은 1 뒤에 n개의 0이 온다는 것이고, 그 수에서 1만큼만 빼준 수가 위의 10진법의 경우에서처럼 패턴이 되어주는 수가 될 것이다. 예를들어 n=4인 4자리 2진법 수에 대해서는 (10000)2가 얻어지고. 거기서 1을 뺀다면

(1111)2 라는 수가 얻어질 것이다. 즉 2진수의 1의 보수는 n자리만큼 있는 1 이라고 생각하면 된다.

그렇다면 여기서 감소된 기수보수를 구하기 위해선 본래의 N이라는 수를 빼야하는데.... 

2진법의 특성상 1111이라는 수에서 0과 1로 이루어진 수를 빼게 된다면 N의 수에서 0과 1만 서로 바꾸어준 결과가 나온다. (ex. 1111 - 1010 = 0101) 

(사실 이 특성이 2진법에 익숙하지 않아서 왜그런지 납득이 안된다면 그냥 0과 1을 바꾸어서 나타내면 되겠구나 ! 라고 생각해도 무방하다.)

예를 더 들어보자.

 

1011000에 대한 1의 보수(감소된 기수보수)는 7자리 이므로 7개의 1을 가지면 된다.

1111111 - 1011000 = 0100111 

 

예시에서도 볼 수 있듯이 본래의 수 N 1011000에대한 1의 기수보수는 0과 1이 반전된 0100111이라는 결과가 나온다.

(2진수에 대해서 외워둘 특징)

 

이러한 특성들로 미루어 볼 때. 8진수 또는 16진수에 대한 감소된 기수보수는 각각 7, 혹은 F(10진수로 15)을 자릿수만큼 써놓고 각 N이라는 숫자를 빼 구하면 되는 것이다.


자 위에서 열심히 이해가 가질 않는 '감소된 기수 보수'를 구해보았다면 이번엔 '기수 보수'이다.

보수에 대한 내용을 아무리 이해해보려고 노력해도 '이걸 왜 하고있지?' 라는 생각이 든다면 납득하기가 쉽지 않다.

그러나 조금만 참고 기수보수를 구하는 방법까지 알고 있다면. 

결국 컴퓨터에게 뺄셈을 어떻게 시켜야 하길래 보수를 구해서 하는것인지 알게 될 것이다.

 

기수보수의 정의를 다시 보자.

이것을 위에서 해본 감소된 기수 보수와 비교해 볼 때.  기수보수는 감소된 기수보수에 +1 을 더해서 구한다.

예를 들어보자.

10진수 2389에 대한 10의 보수는 r=10 n=4 이므로. 감소된 기수 보수를 구하는 식은

9999 - 2389 = 7610 일 것이고. 여기에 +1을 하면 

7611 이 된다.

또한, 2진수 101100에서는 r=2 n=6 이므로. 감소된 기수 보수를 구하는 식은

111111 - 101100 = 010011 이고. 여기에 +1을 하면

010100 이 되고. 이것이 기수보수를 구한 값이 된다.

 

이렇게 우리는 감소된 기수보수를 구하는 방법과 패턴을 알고 있으므로, 감소된 기수보수에 +1을 해 기수보수를 구한다.

그러나, 감소된 기수보수와 마찬가지로 기수보수 또한 연산중 특징이 나타나는데 이 패턴을 파악하면 더 쉬워진다.

 

- 10진수의 기수 보수 구하는 패턴 -

① 최하위 유호 자리 0은 변경하지 않는다.

② 첫번째로 0이 아닌 최하위 유효 자릿수는 10에서 뺀다.

③ 그보다 높은 모든 유호 자릿수들은 9에서 뺀다.

 

위에서 예를 들었던 10진수 2389로 패턴을 적용해 보자.

첫번째. 최하위 유효 자리 0은 변경하지 않는다. -> 2389에는 최하위 유효자리 0이 없다.

두번째. 처음으로 0이 아닌 유효 자릿수는 10에서 뺀다. -> 일의자리 9가 첫 유효자릿수 이므로 10 - 9 = 1 이다.

세번째. 그보다 높은 모든 유효 자릿수는 9에서 뺀다. -> 다음 모든 자리는 9에서 뺄셈한다. 9-2, 9-3, 9-8

결론적으로 각 자리에 맞게 뺄셈을 한 이후 나열해 보면 7611 이라는 앞서 구한 기수보수값이 나타난다 !

 

예시를 몇가지 더 들어서 패턴을 연습해보자.

 

1) 10진수 012398 에 대한 10의 보수

최하위 0이 존재하지 않으므로. 일의자리는 10에서, 그 외 나머지는 모두 9에서 뺀 다음 적어준다.

 

(9 - 0) (9 - 1) (9 - 2) (9 - 3) (9 - 9) (10 - 8) = 9 8 7 6 0 2

 

2) 10진수 246700에 대한 10의 보수

최하위 0이 존재하므로 0으로 표시된 하위 자리 (십의자리와 일의자리)는 변함없이 0을 적는다.

그 이후 처음 등장하는 유효숫자는 7이므로 그 자리만 10에서 빼고 나머지는 9에서 빼준다.

 

(9 - 2) (9 - 3) (9 - 6) (10 - 7) ( 0 ) ( 0 ) = 7 6 3 3 0 0

 

똑같이 2진수의 기수보수도 구하는 패턴이 존재하는데. 방법은 더 쉽다.

 

- 2진수의 기수 보수 구하는 패턴 - 

① 모든 최하위 유효자리 0과 첫번째로 등장하는 1은 변경하지 않는다.

② 다른 모든 상위 유효 자릿수는 1을 0으로, 0을 1로 바꾸어서 구할 수 있다

 

예를 들어서 연습해보자.

 

1) 1101100에 대한 2의 보수

최하위 유효자리는 0이던 1이던 변하지 않는다. 또한 처음으로 1이 등장하기 전까지 변하지 않는다.

처음으로 등장하는 1은 세번째 자리부터 이므로. 최하위 세 자릿수는 변하지 않는다. 그 외는 0과 1을 반전시킨다.

 

0010100 (빨간색은 반전된 부분, 파란색은 변하지 않는 부분)

 

2) 0110111에 대한 2의 보수 

최하위 유효자리는 그대로이고, 그 유효자리는 1 이므로 처음으로 등장하는 자리와 최하위 유효자리가 동일하다.

그러므로 최하위 유효자리와 첫 등장하는 1이 동시에 적용되므로 최하위 유효자리만 변하지 않는다.

변하지 않는 부분을 제외한 나머지는 반전시킨다.

 

1001001 (빨간색은 반전된 부분, 파란색은 변하지 않는 부분)

 

 

자. 여기까지 감소된 기수 보수와 기수 보수 모두를 구하는 방법과 그 패턴을 알아봤다. 

위의 패턴만 기억하고 있다면, 보수를 이해하지 않고 보수를 구할 수 있다. (일단 구할수는 있다는게 중요)

여기에서 소수점이 있는 수에 대한 보수는 언급하지 않았는데. 소수점이 있는 경우에는 소수점을 없다고 생각한 후 보수를 구하고, 그 이후 구한 보수 뒤에 똑같은 소수점을 붙여주면 된다.

 

또한 특정 수의 r 보수에서. 다시한번 r의 보수로 구해주면 본래 특정 수 N이 등장한다. (복원된다)

 

이 보수의 특징은 그냥 기억하고 있어야 한다. 이 특징을 이해하기 위해 정의로 풀어보자면.

특정 N에대한 r의 보수
구한 보수의 보수

으로 이해할 수 있다.


자. 이제 이해가지 않던 수의 보수를 활용해서. 이 망할 컴퓨터에게 뺄셈을 시킬 수 있다.

사실 이렇게 보수를 이용해서 컴퓨터에게 뺄셈을 시키는 이유는. 사람과 다르게 뺄셈을 수행하기 위해서이다. (효율문제)

사람은 뺄셈을 '빌림'의 개념을 이용하며 풀어낸다. 이 방법은 피감수 자릿수가 감수의 자릿수보다 작을 떄 더 높은 유효 자리에서 1을 빌려서 사용하는데. 이 방법은 사람들이 종이와 연필을 가지고 할 때에는 효과적이지만, 디지털 하드웨어를 사용하여 뺄셈을 구현할 때 이 방법은 보수를 사용하는 방법보다 효율성이 떨어진다.

만약 뺄셈의 결과가 음수가 나오는 값이라고 생각해보자. 사람은 수를 '비교'해서 무엇이 큰 수인지 알고 난 이후에 음수라는 기호를 하나만 붙여주면 계산이 끝나지만, 이걸 하드웨어를 통해서 프로그래밍을 하려고 하면 그냥 두 수를 뺄셈한다는 간단한 작업이 아닌. 수의 비교 - 수의 뺄셈 - 부호 결정 이라는 복잡한 과정이 되어버린다.

하드웨어 설계의 효율성이 엄청나게 떨어지는 것이다.

그러나 우리가 배운 보수를 이용한다면. 뺄셈을 덧셈처럼 할 수 있게 된다.

 

- 보수를 이용한 뺄셈 -

기수가 r인 n자리의 부호없는 두 수의 뺄셈 M - N은 다음과 같이 수행할 수 있다.

 

1. 피감수 M에 감수 N에 대한 r의 보수를 더한다.

2. M ≥ N 이라면 그 합은 최종자리올림(end carry) r^n을 생성할 것이고 이것을 제외한 남은 숫자는 M - N의 결과이다.

 

3. M < N 이면 그 합은 최종자리올림을 생성하지 않으며, (N - M)에 대한 r의 보수인

과 같다. 친숙한 형태의 답을 얻으려면 합에 대한 r의 보수를 구하고, 음의 부호를 앞에 붙인다.

 

이 과정은 글로 쓰면 정말 뭐라는지 모르겠다.. (보수를 배우는 과정이 모두 그런가 보다..) 그러나 예시를 보면 쉽다.

피감수는 M, 감수는 N이다. 여기서 N에대한 10의 보수를 구하면 96750 이 구해진다. 이 때 

으로 나타내기 위해 M과 N에대한 10의 보수를 더한다. = 169282

여기에서 M ≥ N 이므로 최종자리올림 (end carry)를 생성한다. (r^n)

end carry를 제외한 뒷자리 값은 M-N임을 나타내고. end carry라는 값이 나왔으므로. M ≥ N이라고 판단한다.(부호)

1.5의 예제와 같이. 감수의 10의 보수를 구하면. 27468 이고. 이를 피감수 M과 더한다.

더한 결과값은 30728 이고. 앞의 최종자리올림이 없으므로. M ≤ N 으로 판단한다. (end carry 없음)

결과적으로 음수의 부호를 판단하고. 그 결과값은 30728 이라는 크기로 - 30728임을 알 수 있다.

 

예제로 직접 풀어보면 훨씬 쉽다는 것을 느낄 수 있다. 그냥 우리가 지금까지 해온 보수를 이용해서 피감수와 더하고. 그 앞에 end carry가 있다면 양수, 없다면 음수로 판단하고. 발생한 end carry는 버리면 그 뺄셈연산의 결과가 나온다.

 

가장 중요한 2진수의 경우도 예시를 들어서 보자.

앞의 과정과 똑같다. (a)는 피감수를 X (b)는 피감수를 Y로 놓고 서로 2의 보수를 이용한 뺄셈의 과정이다.

모든 계산의 과정은 동일하므로, 연습 예제를 한 문제 더 보면서 마무리 하겠다.

 

 

 

728x90