Jay의 자취들

#4-2 파이썬 비트연산자, 2의 보수 공부하기 본문

같이 공부하는 6코딩9/6파이썬9

#4-2 파이썬 비트연산자, 2의 보수 공부하기

Jay Jeong 2021. 12. 6. 05:22


안녕하세요 재이입니다.
오늘은 비트 연산자에 대해서 배워볼 거예요.
그 전에! 비트 연산자를 이해하기 위해선 2진수에 대해 이해해야 합니다.
그럼 먼저 2진수에 대해 배워볼까요?



2진수란 1과 0으로만 이루어진 숫자입니다.
일상생활에선 10진수를 사용하지만 컴퓨터는 2진수를 사용합니다.

10진수와 2진수


네? 무슨 소린지 모르겠다고요?
이제부터 하나씩 설명드릴게요!

만약 235라는 숫자가 있습니다.
숫자 235를 10진수로 표현하면 2X(10^2) + 3X(10^1) + 5X(10^0) 이렇게 되는 것처럼
235를 2진수로 표현하면 1X(2^7) + 1X(2^6) + 1X(2^5) + 0X(2^4) + 1X(2^3) + 0X(2^2) + 1X(2^1) + 1X(2^0)
=11101011 이 됩니다.

이때의 ^는 제곱 표시입니다.


네? 2의 7승에는 1을 곱하고, 2의 4승에는 0을 곱하는지 어떻게 아냐고요?
10진수를 2진수로 바꾸는 계산은 나눗셈을 이용하시면 됩니다.


235를 2로 나누면 몫은 117, 나머지는 1이므로 위의 그림과 같이 적어줍니다.
몫 117을 2로 나누면 몫은 58, 나머지는 1이므로 위의 그림과 같이 적어줍니다.
몫 58을 2로 나누면 몫은 29, 나머지는 0이므로 위의 그림과 같이 적어줍니다.
더이상 나눌 수 없을 때까지 반복해주세요.
그리고 빨간 화살표 순서대로 숫자를 읽어 내려가면 10진수 숫자를 2진수 숫자로의 변환을 마쳤습니다!

그런데..파이썬에는 10진수를 2진수로 변환하는 함수가 있다는데요?

손으로 구할 필요가 없습니다!


10진수를 2진수로 변환해주는 함수 bin을 사용하여 235를 2진수로 표현한 결과는 0b11101011입니다.
위에서 직접 손으로 구한 값과는 조금 다르게 앞에 0b가 붙었네요.
이때 0b는 뒤의 11101011이 10진수 숫자가 아닌 2진수 숫자임을 나타내는 문자입니다.
이렇게 컴퓨터는 숫자를 포함한 모든 정보를 2진수로 바꿔 저장하는데 이때 2진수 글자 하나를 비트라고 합니다.

비트 연산자는 2진수로 바뀐 정보를 연산하는 기호입니다.
비트 연산자에는 6가지 종류가 있습니다.
&, |, ^, ~, <<, >>
하나씩 살펴볼게요.

a=69, b=15라 가정하고 a와 b를 이진수 계산법에 의해 2진수로 나타내면 a=1000101, b=0001111입니다.
자릿수를 맞추기 위해 1111 앞에 세 개의 0 붙여줌.

1은 참을 의미하고 0은 거짓을 의미한다고 생각해주세요.

연산자(operator) 의미(description) 예시(example)
& AND 연산, 둘 다 참일 때 만족 a & b = 12 → 0b0000101
| OR 연산, 둘 중 하나만 참이여도 만족 a | b = 79 → 0b1001111
^ XOR 연산, 둘 중 하나만 참이면 만족 a ^ b = 74 → 0b1001010
~ 보수 연산 ~b = -16 -0b10000
<< 왼쪽 쉬프트 연산, 변수의 값을 왼쪽으로 지정된 비트 수 만큼 이동 b << 2 =60 → 111100
>> 오른쪽 쉬프트 연산, 변수의 값을 오른쪽으로 지정된 비트 수 만큼 이동 a >> 3 = 8 → 1000

a=1000101
b=0001111
같은 자리끼리 연산해봅시다.
& 연산자는 둘 다 참, 즉 둘 다 1일 때 만족하는 연산자입니다.
첫 번째 자리에서 a는 1, b는 0, 둘 다 1이 아니므로 첫 번째 자리는 0이 나옵니다.
두 번째 자리에서 a는 0, b는 0, 둘 다 1이 아니므로 두 번째 자리는 0이 나옵니다.
쭉쭉 넘어가서 다섯 번째 자리에서는 a는 1, b는 1, 둘 다 1이므로 다섯 번째 자리는 1이 나옵니다.
이렇게 해서 a & b는 0000101, 10진수로는 12가 나오게 됩니다.


| 연산자는 둘 중 하나가 참, 그러니까 둘 중 하나가 1이 나오면 그 자리에는 1을 반환합니다.


^ 연산자는 둘 중 하나만 참, 그러니까 두 수가 서로 다른 숫자가 나와야 그 자리에는 1을 반환합니다.


~ 연산자를 배우기 전, 우리는 보수라는 개념부터 이해해야 합니다.

보수란 보충하는 수를 의미합니다.

익숙한 10진수로 예를 들어볼게요.10진수에는 10의 보수9의 보수가 사용됩니다.10의 보수란 숫자의 합을 10의 제곱수로 만들어주기 위해 더해줘야 하는 수입니다.또한 9의 보수란 숫자의 합을 10의 제곱수 -1로 만들어주기 위해 더해줘야하는 수입니다.→9의 보수는 각 자리수의 값에 9에서 빼주면 구할 수 있습니다.9의 보수를 사용해 10의 보수를 다시 설명하면 10의 보수는 9의 보수를 취한 후 +1을 하면 구할 수 있습니다.→다시 말해 10의 보수는 각 자릿수의 값을 9에서 빼준 후 +1을 하면 됩니다!

이해가 안 될 수도 있으니 예를 들어 설명하겠습니다.

10진수 4의 9의 보수는 5 입니다. 9 - 4 = 5 (각 자리수의 값을 9에서 빼줌)10진수 4의 10의 보수는 6입니다. 9 - 4 + 1 = 6 (9의 보수를 취한 후 +1 즉, 각 자릿수의 값을 9에서 빼준 후 +1)

또 다른 예를 들어볼게요.10진수 12의 9의 보수는 87입니다. 99 - 12 = 87 (각 자리수의 값을 9에서 빼줌)
10진수 12의 10의 보수는 88입니다. 99 - 12 + 1 = 88 (마찬가지로 9의 보수를 취한 후 +1)

그렇다면 컴퓨터가 사용하는 2진수에서는 2의 보수와 1의 보수가 사용되니 2의 보수와 1의 보수를 구해볼까요?
먼저 2의 보수란 숫자의 합을 2의 제곱수로 만들어주기 위해 더해줘야 하는 수입니다.
1의 보수란 숫자의 합을 2의 제곱수 -1로 만들어주기 위해 더해줘야 하는 수입니다.
→1의 보수는 각 자릿수를 1에서 빼면 구할 수 있는데 이는 비트를 뒤집는 것과 동일합니다.

예를 들어볼게요.
2진수 1001의 1의 보수는 0110입니다. 1111 - 1001 = 0110 (각 자릿수의 값을 1에서 빼줌=비트 뒤집기)
2진수 1001의 2의 보수는 0111입니다. 1111 - 1001 + 1 = 0111 (1의 보수를 취한 후 +1, 즉 각 자리수의 값을 1에서 빼준 후 +1)

그렇다면 컴퓨터는 왜 보수를 사용할까요?
컴퓨터는 음수를 표현하기 위해 보수를 사용합니다.
그러면 컴퓨터는 왜 음수를 표현할까요?
컴퓨터는 뺄셈 연산을 하지 못하기 때문에 양수를 2의 보수를 사용해 음수로 만들어준 후 덧셈 연산을 하는 형식으로 바꿔줘야 합니다.
예를 들어 우리는 7 - 3 = 4라는 뺄셈 연산을 할 수 있지만 컴퓨터는 못 하기 때문에 3의 2의 보수를 구해 7 + (-3) = 4 이딴식으로 덧셈 연산을 처리합니다. 좆같

컴퓨터가 2진수를 음수로 표현하는 방법은 3가지나 있으나 그중 2의 보수를 선택한 이유를 설명하기엔 난이제지쳤어요

그럼 실제 연산을 보겠습니다.
'5 - 2'라는 연산을 처리하기 위해 먼저 컴퓨터는 10진수를 2진수로 변환할 것입니다.
그러면 '101 - 010'으로 변환되겠죠. 그런데 컴퓨터는 뺄셈 연산을 못 하므로 2진수 10의 2의 보수를 취해 덧셈 연산으로 변환하겠습니다.
2진수 010의 2의 보수를 구하기 위해 먼저 1의 보수를 취한 후 +1을 하면, 111 - 010 + 1 = 110 즉, 010의 2의 보수는 110이 나옵니다.
결국 컴퓨터가 처리하는 연산은 '101 + 110' 이 되겠네요.
계산을 해보면 101 + 110 = 1011 음?! 우리가 구해야 할 값은 3(10) = 011(2)인데?! 틀렸나?!
틀리지 않았습니다!
우리는 3비트짜리 자료(101, 110)를 사용했기 때문에 데이터 표현 범위를 초과한 자료는 무시할 겁니다. 3비트 메모리에 4비트 자료를 쓸 순 없잖아요. 그리하여 1011에서 밑줄 친 1을 버리면 우리가 구해야 할 011이 나오게 됩니다!



이제 드디어 ~연산자에 대해 알아보도록 하겠습니다.
~연산자는 모든 비트를 뒤집어주면 됩니다.
예를 들면 5 = 0101이므로 ~5 = 1010이 되겠네요


음? 왜 1010이 안 나오는 거죠?
왜냐하면 1010은 컴퓨터가 인식하는 ~5이고, 이는 컴퓨터가 연산을 하기 위해 자신만의 방식(2의 보수)으로 음수를 저장한 것입니다.
친절한 컴퓨터는 인간을 위해 자신만의 방식으로 저장한 음수를 인간에게 익숙한 2진수로 해독해서 보여준 것입니다.

그럼 친절한 컴퓨터가 인간을 위해 2진수로 해독한 방법을 친절한 재이가 알려드리겠습니다.
음수를 저장하기 위해 2의 보수를 취했으므로 음수를 해석하기 위해선 2의 보수를 역을 취해주어야 합니다.
다시 말해 음수를 저장하기 위해 1의 보수를 취하고 +1을 했으므로 음수를 해석하기 위해선 -1을 해주고 1의 보수를 취해주어야 합니다.

예시를 들어볼게요.
~5 = 1010은 2의 보수를 취한 후 저장된 음수입니다.
이를 해석하기 위해 먼저 -1을 해주면 1001이 나옵니다. 1001에 1의 보수를 취해주면 0110이 나오게 됩니다.
그런데 음수라고 했는데,, 음수인지 양수인지 어떻게 알까요? 그건 바로 MSB를 통해 알 수 있습니다.
MSB란 Most Significant Bit로 가장 최상위 비트 즉, 가장 왼쪽 비트를 통해 알 수 있습니다.
가장 왼쪽 비트가 0이면 양수, 1이면 음수입니다.
5는 0101 → 최상위 비트가 0이므로 양수이고, ~5는 1010 → 최상위 비트가 1이므로 음수라는 것을 알 수 있습니다.
그래서 위의 사진처럼 ~5를 print함수를 사용해 우리가 아는 2진수로 표현하면 -0b110 = -6이 나오게 됩니다. 0b앞의 -는 음수라는 것을 보여주기 위한 표시라고 생각하시면 됩니다.

~연산자 공식은 ~x = -(x + 1)입니다. 공식만 알면 되긴 하는데 원리를 이해해야 뭔가 배운 것 같잖아요?
원리 이해하셨으면 그냥 공식 외워서 쓰세요ㅎ


<<연산자는 왼쪽 쉬프트 연산자로 비트를 지정된 숫자만큼 왼쪽으로 옮겨주시면 됩니다.
15 << 2의 경우를 볼게요. 15의 2진수 표현은 1111입니다. 이를 왼쪽으로 2번 옮기고 공백이 생긴 자리에는 0을 넣으면 111100, 10진수로는 60이 나오겠네요.
왼쪽 쉬프트 연산자는 왼쪽으로 한 번 이동할 때마다 2배가 됩니다. 15를 왼쪽으로 2번 이동했으므로 15*2*2 = 60이 나옵니다.

>>연산자는 오른쪽 쉬프트 연산자로 비트를 지정된 숫자만큼 오른쪽으로 옮겨주시면 됩니다.
69 >> 1의 경우 1000101에서 오른쪽으로 1번 옮겼으므로 100010이 되고, 69 >> 2의 경우 1000101에서 오른쪽으로 2번 옮겼으므로 10001이 되고, 마지막으로 69 >> 3의 경우 1000101에서 오른쪽으로 2번 옮겼으므로 1000, 10진수로는 8이 나옵니다.



오늘은 비트 연산자에 대해 배워보았습니다.
비트 연산자 중 ~연산자 때문에 죽는 줄 알았네요. 분명 머리로는 알겠는데 글로 쓰려니까 막막해서 어제 6시간 동안 이새끼 붙잡고 있느라 시험공부 죽쒔습니다,..하..
그럼 안녕!


다른 포스팅 보기

#4-1 파이썬 연산자(산술, 비교,할당 연산자)

안녕하세요 재이입니다. 오늘은 파이썬 기본 연산자 중 산술 연산자, 비교(관계형) 연산자, 할당 연산자에 대해 배워볼 거예요. 기본 연산자에 7가지 연산자가 있습니다. 1) 산술 연산자, 2) 비교

jays-log1111.tistory.com

#2 파이썬 자료형(숫자, 문자열, boolean) 공부하기

안녕하세요 재이입니다. 오늘은 파이썬 자료형에 대해서 알아볼 거예요. 3가지 자료형이 있습니다. 1) 숫자 자료형, 2) 문자열 자료형, 3) boolean 자료형 첫 번째로는 숫자 자료형이 있습니다. 숫자

jays-log1111.tistory.com



p.s.
같이 공부하는 6코딩9은 프로그래밍 초보에서부터 고수까지 가는 여정을 담을 거예요. 아직은 초보입니다?
차근차근 꾸준히 하다 보면 나만의 포트폴리오를 만들 실력이 생기겠죠?
그럼 고수 재이를 볼 그날까지..
화이팅!

Comments