본문 바로가기
Apple/Swift

[Swift] 비트 연산과 비트마스킹 (NOT, AND, OR, XOR, 시프트 등)

by 어멘드 2022. 1. 17.
반응형

 오늘도 PS를 위한 문법, 비트 연산자이다. 비트 연산은 거의 비트마스킹에 쓰기 때문에 비트마스킹에 활용하는 방법까지 엮어서!

 


Bitwise Operators

 

NOT ( ~ )

 모든 비트를 반대로 뒤집어버린다. 0은 1로 만들고, 반대로 1은 0으로 만든다. 연산자는 ~이다.

let A: UInt8 = 0b00110011   // 0011 0011
let notA = ~A               // 1100 1100

 

AND ( & )

 둘 다 1인 경우에만 1이고, 나머지 경우는 모두 0으로 만든다. 연산자는 &이다.

let A: UInt8 = 0b00110011   // 0011 0011
let B: UInt8 = 0b01010101   // 0101 0101
let AandB = A & B           // 0001 0001

 

OR ( | )

 둘 중에 하나라도 1인 경우에는 1이고, 둘 다 0인 경우에만 0으로 만든다. 연산자는 |이다.

let A: UInt8 = 0b00110011   // 0011 0011
let B: UInt8 = 0b01010101   // 0101 0101
let AorB = A | B            // 0111 0111

 

XOR ( ^ )

 두 비트가 다르면 1, 같으면 0으로 만든다. 연산자는 ^이다.

let A: UInt8 = 0b00110011   // 0011 0011
let B: UInt8 = 0b01010101   // 0101 0101
let AxorB = A ^ B           // 0110 0110

 

Shift ( << ,  >> )

 N칸 만큼 각 모든 비트를 왼쪽 또는 오른쪽으로 민다. 밀고 나서 생긴 빈 비트를 무엇으로 채울지는 자료형이 Signed인지 Unsigned인지에 따라 다르다고 하는데, 비트마스크 용으로 시프트를 공부하고 있기 때문에 Unsigned인 경우만 생각해주자..ㅎㅎ Unsigned는 빈자리를 0으로 채운다. 왼쪽 시프트 연산자는 <<, 오른쪽 시프트 연산자는 >> 이다.

let unsigned: UInt8 = 0b11111111
let shiftRight = unsigned >> 4      // 00001111
left shiftLeft = unsigned << 4      // 11110000

 


Bitmask

 용도는 Int를 [Bool]처럼 사용하는 것이다. N개의 원소에 대해 각각 true/false를 기록해야 하는 상황이다. Int를 이진수로 표현하면 각 비트는 1 아니면 0이므로 이것을 true/false로 사용할 수 있게 된다!

 단, N이 자료형의 크기만큼으로 제한된다. Int32면 32개의 비트로 표현되므로, N=32까지, Int64라면 N=64까지 가능하다. 이렇게 N이 작은 경우에는 [Bool] 대신 쓰면 시간과 메모리 측면에서 효율적이다.

 이제 비트마스킹의 각 연산을 알아보자. 앞으로 언급하는 N번째 원소는 오른쪽에서 N번째 비트이다.

 

N번째 원소를 true(1)로 만들기

 

 N번째 비트에 1을 OR 연산해주면 될 것이다. 나머지는 그대로 두어야 하므로 N번째 비트만 1인 이진수 1 << (N-1) 과 OR를 해준다.

// 3번째 원소를 1로 만들기
var bitmask: UInt8 = 0b11111011     // 1111 1011
bitmask |= (1 << 2)                 // 1111 1111

 

N번째 원소를 false(0)로 만들기

 N번째 비트에 0을 AND 연산해주면 될 것이다. 나머지는 그대로 두어야 하므로 N번째 비트만 0인 이진수 ~(1 << (N-1))과 AND를 해준다.

// 3번째 원소를 0으로 만들기
var bitmask: UInt8 = 0b00000100     // 0000 0100
bitmask &= ~(1 << 2)                // 0000 0000

 

N번째 원소의 값 확인하기

 N번째 비트에 1을 AND 연산을 한 결과가 0이면 0이고, 1이면 1일 것이다. 나머지가 모두 0이고 N번째 비트만 1인 이진수 1 << (N-1)과 AND를 해주면, 나머지 비트는 모두 결과가 0일 것이기 때문에 1이 나올 수 있는 비트는 N번째 비트밖에 없다. 따라서 결과가 0이면 N번째 비트는 0인 것이고 0이 아니면, N번째 비트는 1인 것이다.

// 4번째, 5번째 원소 확인하기
var bitmask: UInt8 = 0b11110000                     // 1111 0000
let check4thBit = bitmask & (1 << 3) == 0 ? 0 : 1   // 0
let check5thBit = bitmask & (1 << 4) == 0 ? 0 : 1   // 1

 

N번째 원소 토글하기

  N번째 원소 토글은 XOR의 아래와 같은 성질을 이용한다. N번째 비트만 토글하고 싶으면 N번째 비트만 11 << (N-1)과 XOR를 해주면 된다.

1과 XOR 연산을 하면 토글된다.
0 XOR 1 = 1
1 XOR 1 = 0

0과 XOR 연산을 하면 그대로이다.
0 XOR 0 = 0
1 XOR 0 = 1
// 3번째 원소 토글하기
var bitmask: UInt8 = 0b00000000     // 0000 0000
bitmask ^= (1 << 2)                 // 0000 0100

 

반응형

댓글