python 비트연산과 시프트 연산 방법 및 적용 예시


python 비트(bit) 연산과 시프트 연산(shift)의 사용 방법과 활용법에 대해 알아보자.


비트 연산

비트 연산은 이진수로 논리 연산을 한다. 논리 연산에는 AND, OR, XOR, NAND가 있다. 하나씩 살펴보자.

AND( & ) 연산

아래와 같이 두 비트의 연산에서 둘 다 1인 경우에만 1을 반환한다.

1
2
3
4
5
6
>>> 1 & 1
1
>>> 1 & 0
0
>>> 0 & 0
0

이진수가 한자리 수가 아닌 경우 각 자리수를 보고 연산한다. 예를 들어,
이진수 1001과 1101가 있으면, 첫째자리와 넷째자리 수만 둘 다 1이므로, 1을 반환하고 나머지는 0을 반환한다.
그러므로 결과는 1001이된다.

십진수의 경우, 이진수로 변환 후에 계산한다. 예를 들어,
9는 이진수로 1001, 13는 이진수로 1101인데, 이 둘을 비트연산하면 1001이므로 리턴값은 9가 된다.

1
2
3
4
>>> 9 & 13
9
>>> 0b1001 & 0b1101 #이진수로 계산하고 싶은 경우, 0b를 앞에 붙이면 된다.
9

정리하면, 두 개의 이진수를 각자리 별로 진리표에 따라 계산하는 것이다! 간단하다. 계속 살펴보자.

OR( | ) 연산

OR 연산은 둘 중 하나면 1이면 1을 반환한다. 마찬가지로 9와 13을 연산해보자.

1
2
3
4
>>> 9 | 13
13
>>> 0b1001 | 0b1101
13

XOR( ^ ) 연산

XOR 연산은 비교 값이 서로 달라야 1을 반환한다.

1
2
3
4
5
6
>>> 9 ^ 13
4
>>> 0b1001 ^ 0b1101
4
>>> bin(4) #4는 100이다.
'0b100'

비트연산 적용 예시

비트 연산으로 복수 개 값의 포함 여부를 알 수 있다.
예를 들어 사용자가 요일을 선택하면 해당 요일에 알람을 보내는 기능이 있다고 해보자.
이진수 계산을 위해 월요일을 1(20 ), 화요일을 2(21 ), 수요일을 4(22 ),,, 일요일을 64(26 )라고 둔다.
만악 사용자가 월, 수를 골랐다면 1+4 이므로 5이다. 오늘이 월요일이라고 했을 때, 해당 유저에게 알람을 보낼지 확인하려면 AND 비트 연산을 하면된다!

1
2
3
4
5
6
>>> 1 & 5 #월요일은 1이다.
1
>>> 2 & 5 #화요일은 2이며, 유저는 화요일을 선택하지 않았다!
0
>>> 4 & 5 #수요일은 4이며, 유저는 수요일을 선택했다.
4

권한을 지정할 때도 비트연산은 좋은 방법이다. 보통 쓰기 권한이 있으면 읽기 권한도 있는 것이므로, 읽기 권한이 1이면 쓰기 권한은 읽기 권한 값 1과 쓰기 권한 2를 더해 3으로 둘 수 있다. 이 때에는 메뉴의 권한 값과 일치하는 결과를 리턴해야 권한이 있다고 보면된다.
만약 읽기 권한의 유저가 쓰기 권한용 메뉴를 접근하면 아래와 같이 1을 반환할 것이고 이는 쓰기 권한용 값이 아니므로 유저가 접근할 수 없다.

1
2
3
4
>>> 1 & 3 #읽기 권한 유저
1
>>> 3 & 3 # 쓰기 권한 유저
3

만약 읽기 + 쓰기 + 알림 기능을 가진 슈퍼어드민은 1 + 2+ 4 = 7이라면, 쓰기 메뉴에 접근할 수 있다.

1
2
>>> 7 & 3 #슈퍼어드민
3

비트 시프트(shift) 연산

시프트 연산은 지정한 숫자만큼 값을 이동하는 것이다.

<< 왼쪽 shift

지정한 숫자만큼 왼쪽으로 비트를 이동한다. 앞으로 n개만큼 생기는 것이기 때문에, n개만큼 자릿수가 늘어난다.

1
2
3
4
>>> bin(0b1000 << 1) #bin()은 10진수를 2진수로 바꿔준다.
'0b10000'
>>> bin(0b1001 << 2)
'0b100100'

>> 오른쪽 shift

지정한 숫자만큼 오른쪽으로 비트를 이동한다. 뒤로 이동하는 것이기 때문에, n개 만큼 자릿수가 줄어든다.

1
2
3
4
>>> bin(0b1000 >> 1)
'0b100'
>>> bin(0b1001 >> 2)
'0b10'

시프트 연산 서비스 적용 예시

위에서 살펴본 요일 별 알림 서비스를 다시 가져와보자.
이번에는 차례대로 월요일이 0, 화요일이 1, 수요일이 2,,, 일요일이 6이다.
아래와 같이 오른쪽 shift 연산을 통해 2의 n승을 구할 수 있다. 만약 토요일(5)을 예로들면 25인 32란 값이 나온다.

1
2
1 << 5
32

요일을 2의 n승으로 바꿀 필요없이 순서대로 숫자를 매기고 시프트 연산을 통해 계산을 할 수 있다.
사용자가 월, 수, 금요일(1 + 4 + 16 = 21)을 골랐다고 했을 때 아래와 같이 연산할 수 있다.

1
2
3
4
5
6
>>> 21 & 1 << 0 #월요일
1
>>> 21 & 1 << 1 #화요일
0
>>> 21 & 1 << 2 #수요일
4

참고로 시프트 연산자와 비트 연산자가 같이 있으면 시프트 연산부터 계산한다!

Comments