비트 연산자 (Bitwise Operator)
python으로 하드웨어를 다루려면 비트 연산자를 알아둬야 합니다.
자주 사용되는 건 아니지만 비트 단위로 계산하기 때문에 일반 사칙 연산자보다 훨씬 빠릅니다.
&, |, ^의 경우에는진리표 작성에서도 쓰니 패스하고, ~, >>, <<에 신경씁시다.
~는 -(값 +1)을 출력하게 된다. 정확히는 2의 보수의 값을 출력한다.
보수에 대해서는 ndb796.tistory.com/4 여기와 하단 설명을 참고하자.
<< 는 각 비트를 왼쪽으로 옮김(shift). 한번 옮길 때마다 *2^n 하는 효과
>> 는 각 비트르 오른쪽으로 옮김(shift). 한번 옮길 때마다 /2^n 하는 효과
python
a = int(input())
print(~a) # -(val + 1)
print(a << 1) # *2
print(a >> 1) # /2
C
#include <stdio.h>
int main() {
unsigned char input;
unsigned char mul;
unsigned char mod;
scanf("%hhu", &input);
mul = input << 4; // 16배
mod = input >> 3; // 1/8배
printf("%hhu ", mul);
printf("%hhu", mod);
return 0;
}
왜 보수가 필요한가?
두 수의 합이 진법의 밑수가 되게 하는 수를 보수라 한다. 예를 들어 10진법에서 4의 보수는 6이다. 4 + 6 = 10이기 때문이다. 보수가 필요한 이유는 음의 정수를 표현하기 위해서이다.
컴퓨터에 저장되는 모든 데이터들은 2진수 형태로 바뀌어 저장된다. 0과 1로만 구성되는 비트단위들로 변환되어 저장되는데, 양의 정수는 2진수 형태로 바뀌어 저장되고, 음의 정수는 "2의 보수 표현"방법으로 저장된다.
음의 정수를 보수 표현으로 하는 이유는, 칩셋에서는 가산기만 존재하기 때문에 뺄셈은 음의 정수를 더하는 꼴로 계산해야 한다. 즉, A - B를 계산하기 위해 A + ( B의 보수 ) 를 하는 것이다.
보수를 구하는 방법은 간단하다.
- 1의 보수 : 0과 1을 반전하면 1의 보수가 된다.
ex) 1010의 1의 보수는 0101이다.
- 2의 보수 : 1의 보수에 1을 더한 값
ex) 1010의 2의 보수는 0101 에 1을 더한 0110이 된다.
비트의 and 연산
예를 들어 3과 5가 입력되었을 때를 살펴보면 (int 4Byte에 저장한다고 가정)
3 : 00000000 00000000 00000000 00000011
5 : 00000000 00000000 00000000 00000101
3 & 5 : 00000000 00000000 00000000 00000001
이 된다. & 연산이기 때문에 둘 다 1인 부분의 자리만 1로 만들어주는 것과 같다.
아래 python 코드는 True & True가 아니라 비트 단위로 연산된다.
이므로 출력 결과물은 1이다.
print(3 & 5) # output : 1
0011
0101
----
0001
이 연산을 이용하면 어떤 비트열의 특정 부분만 모두 0으로도 만들 수 있는데
192.168.0.31 : 11000000.10101000.00000000.00011111
255.255.255.0 : 11111111.11111111.11111111.00000000
두 개의 ip 주소를 & 연산하면
192.168.0.0 : 110000000.10101000.0000000.00000000 을 계산할 수 있다.
실제로 이 계산은 네트워크에 연결되어 있는 두 개의 컴퓨터가 데이터를 주고받기 위해
같은 네트워크에 있는지 아닌지를 판단하는데 사용된다.
이러한 비트단위 연산은 빠른 계산이 필요한 그래픽처리에서
마스크연산(특정 부분을 가리고 출력하는)을 수행하는 데에도 효과적으로 사용된다.
비트의 or 연산
3 : 00000000 00000000 00000000 00000011
5 : 00000000 00000000 00000000 00000101
3 | 5 : 00000000 00000000 00000000 00000111
이 된다.
비트단위 or 연산은 둘 중 하나라도 1인 자리를 1로 만들어주는 것과 같다.
python으로 예시를 살펴보자면 다음과 같다.
print(3 | 5) # output: 7
0011
0101
----
0111
이러한 비트단위 연산은 빠른 계산이 필요한 그래픽처리에서도 효과적으로 사용된다.
<<, >> 비트 shift 연산
당연히 비트를 왼쪽 혹은 오른쪽으로 1칸씩 움직이는 것이므로 2승으로 곱하거나 나누는 효과를 낸다.
print(5 >> 1) # 2
print(5 << 1) # 10
0101 에서 왼쪽으로 << 움직이면 1010이 되므로 값은 10이되고
오른쪽으로 >> 움직이면 0010이 외므로 2가 된다.
'💻 CS 일반 > 💻 CS 일반 (etc...)' 카테고리의 다른 글
Go로 살펴보는 메모리 정렬(alignment)과 메모리 패딩(padding) (0) | 2021.05.11 |
---|---|
Go로 살펴보는 오버플로, 언더플로, float간 비교 (0) | 2021.05.09 |
Cache의 개념 (0) | 2021.01.31 |
기계어와 어셈블리어, IR(Intermediate representation) (0) | 2020.08.30 |
프로세스, 프로세서(CPU), Context Switching, 스레드, 멀티스레드 (0) | 2020.08.25 |