오늘도 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번째 비트만 1인 1 << (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
'Apple > Swift' 카테고리의 다른 글
[Swift] 배열에서 중복 제거하기 (0) | 2022.02.05 |
---|---|
[Swift] 문자열에서 특정 문자 한 개 또는 여러 개 제거하기 (0) | 2022.01.18 |
[Swift] 진수 변환하기 (2진수, 8진수, 10진수, 16진수 등) (0) | 2022.01.17 |
[Swift] 거듭제곱하기 (0) | 2022.01.15 |
[Swift] 소수점 제거하기 (반올림, 올림, 내림, 버림 등) (0) | 2022.01.13 |
댓글