본문 바로가기

dev

보수연산?? 그게 뭔데..

[python] 기본 연산자(4) - 논리연산자, 비트연산자

위 글에서 이어집니당


보수가 뭔지 알기 전에 보수가 왜 필요한지 알아보자

우리 컴퓨터는 생각보다 능력이 없기 때문에 숫자 앞에 마이너스 부호를 못 붙인다... 

대신 이진수 형태에선 최상위 비트를 0으로 표현하면 양수 1로 표현하면 음수로 여긴다

이 때 바뀌는 최상위 비트를 MSB(Most Siginificant Bit), 또는 부호 비트라고 한다

예를 들어 4비트 메모리에선 다음과 같은 방식으로 음수를 표현한다

0 0000 -0 1000
1 0001 -1 1001
2 0010 -2 1010
3 0011 -3 1011
4 0100 -4 1100
5 0101 -5 1101
6 0110 -6 1110

위 표에 따르면 5-5는 5+(-5) 와 같고 이건 0101+1101인데

결과값이 10010 이다 0000이 아니고

 

멍청하게도 덧셈은 똑바로 가능한데 뺄셈을 못한다

놀랍게도 원래 컴퓨터에는 뺄셈이라는 개념이 없다

그래서 뺄셈을 할 수 있게 만든 게 보수연산법이다


자 보수란게 뺄셈을 위해서 필요하다는건 알겠다..

 

보수는 뜻풀이로는 '도와주는 수'다

그래서 뭘 도와주냐면...

숫자를 완성시키는걸 도와준다

 

예를 들어 7은 10을 완성시키기 위해 3이 더 필요하다

이 경우는 7의 10의 보수는 3이라고 한다

 

n진법에는 n의 보수 n-1의 보수 2가지가 있다

익숙한 10진법을 예로 들면 10의 보수와 9의 보수가 있는 것이다

 

n진법에서 x의 자리수를 m이라고 하면

n의 m제곱수를 만들어주기 위해서 x에 더해줘야 하는 값을 x의 n의 보수라고 한다

 

10의 보수는 10의 m제곱수를 만들어주기 위해 더해줘야 하는 수

=각 자리 수의 값을 9에서 빼버리고 1을 더한 수

9의 보수는 10의 m제곱수-1를 만들어주기 위해 더해줘야 하는 수

=각 자리 수의 값을 9에서 빼버린 수

 

예를 들어 10진법에서

7의 10의 보수는 3이다  --> 9-7+1 = 3

7의 9의 보수는 2이고    --> 9-7 = 2

 

87의 10의 보수는 99-87+1 = 13이다

 

7은 1자리고 10의 1제곱수를 만들어주기 위해 3이 필요하고

87은 2자리고 10의 2제곱수를 만들어주기 위해 13이 필요하다

 

말이 좀 긴데 우리는 여기서

X의 보수가 Y일 때 Y의 보수가 X인 것을 알 수 있다

~X=Y일 때

~Y=X라는 것이다

 

자 이걸 이진법에 대입해보자

이진법도 똑같이 2의 보수와 1의 보수를 가지고 있다

 

2의 보수는 2의 m제곱수를 만들어주기 위해 더해줘야 하는 수

=각 자리 수의 값을 1에서 빼버리고 1을 더한 수

1의 보수는 2의 m제곱수-1를 만들어주기 위해 더해줘야 하는 수

=각 자리 수의 값을 1에서 빼버린 수

 

말이 너무 긴가?

간단하게 말해서

1의 보수 +1 = 2의 보수 라고 할 수 있다

 

Q . 그럼 굳이 보수를 왜 쓰느냐?

A . 위에서 설명했듯 음수를 저장할 수 있기 때문이다

Q . 어떻게..?

A . 밑에서 설명할 거다


자 우리 이제 보수가 왜 필요한지도 알았고

보수가 뭔지 정확히는 이해가 안 가더라도 보수를 구할 수는 있게 됐다

그럼 보수를 가지고 어떻게 뺄셈을 한다는 말인가?

 

앞서 컴퓨터는 음수를 부호화절대값 방식으로 나타낸다고 했다 ( ex) 1000 1010 )

그럼 컴퓨터는 어떤 과정을 통해서 음수를 저장할까?

 

가령 -10을 8비트 메모리에 저장할 때는 다음과 같은 과정을 거친다

  1. -10을 2진수 형태로 표현 음수니까 DSM은 1 --> 1000 1010
  2. 부호비트를 제외하고 1의 보수로 전환         --> 1111 0101
  3. 1의 보수에 1을 더해서 2의 보수로 저장       --> 1111 0110

결과적으로 1111 0110 이라는 값으로 저장하게 되는데 이건 246의 이진수 표현이 아니다 

-10을 2의 보수형태로 저장한 값이다


자, 이제 보수가 왜 필요한지, 뭔지, 어떻게 계산하는지도 알았으니

~ 연산자에 대해 알아보자

~ 의 기능은 각 비트의 수를 반전하는 것이라고 이전 글의 표에서 설명했다

반전...? 어디서 많이 보지 않았나?

그렇다 이진수를 그 수의 1의 보수로 만들 때 0을 1로 1을 0으로 반전시켰었다

 

우리는 위에서 컴퓨터가 음수를 저장할 때 

이진수로 표현함--> 1의 보수 --> 2의 보수 의 순서로 저장하는 것을 알고 있었다

보수 연산자도 같은 방식을 따른다

 

쉽게 그럼 0을 보수연산해보자

 

0000 0000 은 0이다 그럼 ~0은 0을 전부 뒤집으라는 뜻인걸 알고 있다

1111 1111 인데 맨 앞의 1은 -부호라고 앞서 말했다 부호는 건들지 않고 나머지만 1의 보수로 표현하면

1000 0000 이고 2의 보수로 바꾸기 위해 1을 더하면

1000 0001 이 나온다 여기서 맨 앞의 부호는 -를 뜻하고 그 외의 2진수는 1을 뜻한다

 

그럼 결국 ~0은 -1이 된다

 

~10도 계산해보자

 

0000 1010

1111 0101 --> ~10

1000 1010 --> 1의 보수

1000 1011 --> 2의 보수

~10==-11

 

-1 은 ~0

-11 은 ~10

 

우리는 여기서 -x=~x+1 이라는 결론을 도출할 수 있다

 

이로써 컴퓨터는 2의 보수형태로 음수를 음수부호 없이 저장할 수 있다

우리는 그래서 ~로 보수연산한 것을 풀어낼때 2의 보수를 한번 더 먹여서 풀어내야 한다

위에서 얘기 했듯 보수의 보수는 원래 수니까


자 그래서 우리 보수연산도 알아봤고...

보수 연산으로 뺄셈을 어떻게 하는지 알아보자

 

10-6을 한다 가정했을 때

컴퓨터는 10+(-6) 이렇게 계산해야한다

 

하지만 우리는 앞서 도출한 공식으로 -6을 ~6+1로 나타낼 수 있는 것을 알 수 있다

10+~6+1

=1010+1001+0001

=1010+1010

=(1)0100 --> 데이터 표현범위를 초과(=오버플로우)한 자료는 버려진다

 

10-6=4

 

이제 뺄셈을 못하는 컴퓨터도 뺄셈이 가능하다!


Q . 1의 보수가 더 쉬운데 왜 수고롭게 1을 더하는 2의 보수를 사용하는 걸까?

A .  0000(+0)의 1의 보수는 1111(-0)이고 2의 보수는 10000이다

     위에서 설명했듯 오버플로우는 버려지기 때문에 0000의 2의 보수도 0000인 것을 알 수 있다

     0의 1의 보수는 1111이라는 자리를 차지했지만 2의 보수는 그 자리를 차지하지 않고

     숫자를 하나 더 표시할 수 있게 된다

     똑같은 메모리에서 숫자를 하나 더 표현할 수 있는게 효율적이니 2의 보수를 사용하는 것이다

'dev' 카테고리의 다른 글

[wecode] project 회고록  (0) 2022.03.13
[project] wecode 1st project - ChickIN  (0) 2022.03.07
[개발자도구] console의 메소드: console.clear()  (0) 2022.01.28
[개발자도구] - console  (0) 2022.01.28
[WEB] semantic web & semantic tag  (0) 2022.01.24