비트 연산은 숫자를 이진수(binary)로 변환한 뒤 연산을 수행하는 것이다.
각 자리가 모두 1일 때만 연산 결과가 1이 나옴
SELECT 10 & 3 AS RESULT;
10은 1010
3은 0011로 이진수를 추출할 수 있다.
각 자리가 모두 1이어야 하므로 0010의 결과가 나오고 십진수로 2에 해당한다.
SELECT 10 | 3 AS RESULT;
각 자리가 하나라도 1이면 연산 결과가 1이 나옴
10은 1010
3은 0011
하나라도 1이면 되므로 1011의 결과가 나오고 십진수로 11에 해당한다.
SELECT 10 ^ 3 AS RESULT;
각 자리에서 하나만 1이면 연산 결과가 1이 나옴
10은 1010
3은 0011
하나만 1이어야 하므로 1001의 결과가 나오고 십진수로 9에 해당한다.
모든 비트를 반전시키는 것으로 1은 0, 0은 1로 바꿈
SELECT ~10 AS RESULT;
10은 1010
0101의 결과가 나오고 십진수로 5에 해당할 거라고 생각된다.
하지만!!
~1010 = ...11110101
이를 2의 보수 해석법으로 하게되면...
11110101을 다시 반전시키고 => 00001010
여기에 1을 더하면 => 00001011
이는 십진수로 11에 해당하므로 결과는 -11이 출력된다!
🚨2의 보수 표현!!!
여기서 2의 보수 표현이라는 내용을 보았다.
음수를 이진수로 표현하는 방법 중 하나라고 한다.
양수와 음수를 같은 이진수로 표현할 수 있게 도와주는 것이다.
2의 보수 계산!!
- 음수의 절댓값을 이진수로 변환
- 이진수의 모든 비트 반전
- 반전된 값에 1 더하기
Example
- -10의 경우 절댓값은 10 이므로 이진수로는 00001010이다.
- 모든 비트를 반전하면 11110101이 되고,
- 반전된 값에 1을 더하면 11110110이 된다.
결국-10 => 11110110이 되는 것이다.
여기에 추가로 ~ 결과까지 뽑아보자면!
11110110은 00001001의 반전값이기에 9의 반전값에 해당하게 된다!!
👉 결론!!
~에 해당하는 비트 연산 값은 -(n+1)의 정수값이 결과로 출력된다!!
비트를 왼쪽으로 이동시킨 뒤, 오른쪽 빈 자리는 0으로 채움
SELECT 10 << 2 AS RESULT;
10은 1010이므로
왼쪽으로 이동시키기 때문에 오른쪽에 0을 2개 붙인다고 생각하면 된다.
101000의 결과가 나오고 십진수로 40에 해당한다.
비트를 오른쪽으로 이동시킨 뒤, 왼쪽 빈자리는 부호 비트로 채움
SELECT 10 >> 2 AS RESULT;
10은 1010이므로
10의 결과가 나오고 십진수로 2에 해당한다.
하단 부호비트 설명을 공부하고 나서... 10 이 1010이면 음수 아니야!??! 라고 생각했다;;;
하지만 비트 길이에 따라 달라진다!
보통 MySQL에서는 32비트 이상으로 처리하므로 10은 00000000 00000000 00000000 00001010 으로 저장되어서 양수로 인식되는 것이다.
🚨 부호 비트
오른쪽 시프트 내용 중에 부호 비트라는 말이 나와서 찾아보았다!
이는 산술적인 오른쪽 시프트에서 숫자의 부호를 유지하지 위함이라고 한다.
논리적 오른쪽 시프트
단순히 왼쪽에 0을 채워넣어 오른쪽으로 미는 방식이다.
1011 -> 0101 이 된다.
산술적 오른쪽 시프트
왼쪽에 부호 비트을 채워 넣는다.
0이면 양수, 1이면 음수를 의미한다.
예를 들어,
0110은 양수 6 / 1110은 음수인 -2 (2의 보수 표현)를 나타낸다.
위의 설명을 통해 논리적, 산술적 시프트를 해보면!! (ex. -10 >> 2)
숫자 -10은 8 비트로 11110110에 해당한다.
보면 산술적 시프트는 부호를 그대로 유지했다.
만약 주어진 숫자의 2번째 자리 비트가 0인지 1인지 확인하고 싶은 경우!
6 & 2 -> 110 & 010 -> 010 -> 2
4 & 2 -> 100 & 010 -> 000 -> 0
결과 값의 십진수가 0이 나오는 경우 그 자리마저 1이 일치하지 않는다는 의미이므로
주어진 수의 이진법 상 2번째 자리는 0임을 알 수 있다.
이렇게 해당 자리의 비트를 확인하는 방법이며,
1, 2, 4, 8 의 숫자로 확인하면 된다.
각각 0001, 0010, 0100, 1000 이므로!!
🤔만약 이와 달리 1,3번째 자리를 확인해야하는 상황이라면,
1, 3번째만 1인 숫자와 비교하면 된다.
0101은 5에 해당하므로 이와 비교하면,
6 & 5 -> 0110 & 0101 -> 0100 -> 4
13 & 5 -> 1101 & 0101 -> 0101 -> 5
1, 3번째 모두 1인지 보려면 => 결과가 5와 일치하는 지 확인
1, 3번째 중 하나라도 1인지 보려면 => 결과가 0보다 큰 지 확인
=> 이를 통해 권한을 부여할 수 있다고 한다.
0001: 읽기 권한0010: 쓰기 권한0100: 실행 권한1000: 관리자 권한
A&B > 0인 경우 B권한 활성화
A&B = 0인 경우 B권한 비활성화를 의미하므로
읽기 권한이 있는가? => 0101 & 0001 로 확인 => 0001이므로 TRUE
쓰기 권한이 있는가? => 0101 & 0010 로 확인 => 0000이므로 FALSE
추가는 OR 연산자( | )를 사용한다.
=> A | B이면 B 권한을 추가한다는 의미가 된다.
ex)0101 | 0010 = 0111 (7) (실행, 읽기 권한에 쓰기 권한 추가)
제거는 ANT NOT 연산자(& ~)를 사용한다.
=> A &~ B는 권한 B를 제거한다는 의미가 된다.
ex)0101 & ~0100 = 0101 & 1011 = 0001 (읽기 권한만 남기)
1~5번은 상단의 연산자 부분과 동일한 내용이다!
SELECT BIT_AND(10, 3);
=> SELECT 10 & 3 AS RESULT;
=> 0010
=> 2 출력
SELECT BIT_OR(10, 3);
=> SELECT 10 | 3 AS RESULT;
=> 1011
=> 11 출력
SELECT BIT_XOR(10, 3);
=> SELECT 10 ^ 3 AS RESULT;
=> 1001
=> 9 출력
SELECT BIT_SHIFT_LEFT(10, 2);
=> SELECT 10 << 2 AS RESULT;
=> 101000
=> 40 출력
SELECT BIT_SHIFT_RIGHT(10, 2);
=> SELECT 10 >> 2 AS RESULT;
=> 10
=> 2 출력
주어진 숫자를 이진법으로 나타냈을 때, 1의 개수를 반환
SELECT BIT_COUNT(10);
=> 1010에서 1의 개수이므로 2 반환
숫자를 다른 진법으로 변환
SELECT CONV(5, 10, 2);
=> 5라는 10진수를 2진수로 변환
=> 101 출력
SELECT CONV('101', 2, 10);
=> 101라는 2진수를 10진수로 변환
=> 5 출력
주어진 숫자를 2진수 문자열로 변환
SELECT BIN(5);
=> '101' 반환 (타입은 문자열)
주어진 숫자를 16진수 문자열로 변환
SELECT HEX(255);
=> 'FF' 반환
주16진수 문쟈열을 바이트로 변환
SELECT UNHEX('4D7953514C');
=> '4D7953514C'를 바이트로 변환한 값 반환