상세 컨텐츠

본문 제목

비트 연산 활용한 PS 꿀팁 2 - 활용편

Study/Tip notes

by Arq.Dev5igner 2024. 10. 16. 01:16

본문

속도가 중요시 되는 문제에서 종종 써먹는 팁 정리

const unsigned char num1 = 0x1;  // hex for 0000 0001 ( 0b00000001 )
const unsigned char num8 = 0x8;  // hex for 0000 1000 ( 0b00001000 )
const unsigned char num16 = 0x10; // hex for 0001 0000 ( 0b00010000 )
const unsigned char num128 = 0x80; // hex for 1000 0000 ( 0b10000000 )
  • 홀수 짝수 판단

홀수는 맨 오른쪽 비트(마지막 비트)가 1인 것을 이용한다.
변수에 마지막 비트만 켜져있는 1(0x1)을 & 연산하여 구분.
나누기가 생각보다 어려운연산이라는 것을 알아두자!

/* 0x01 == 0b00000001 */
if ((num & 0x1) == 0)const unsigned char num1 = 0x1;  // hex for 0000 0001 ( 0b00000001 )
{

}

if ((num & 0x1) != 0) /* 홀수 */ 
{

}

 

  • 음수 양수 판단

16진수는 마지막비트에 8이 오는 것을 이용.

8은 2진수로 바꾸면 1000. 가장 왼쪽에 있는 비트- 최상위비트(MSB)- 가 1이면 음수, 0이면 양수

/* 0x80000000 == 0b10000000000000000000000000000000 */
if ((num & 0x80000000) == 0) /* 양수 */
{

}

if ((num & 0x80000000) != 0) /* 음수 */
{

}




  • XOR swap
int a = 1;
int b = 2;

// swap
int temp = a;
a = b;
b = c;
/********************/
if (a != b) {
    a ^= b;
    b ^= a;
    a ^= b;
}
/********************/
if (a != b) {
    a ^= b ^= a ^= b;
}

 

 

 

 

  • 대소문자 변경

아스키코드의 대문자  5번째 비트가 0,소문자는 1 .

마스크 0b00010000 을 만들어서 XOR연산처리.

//대문자 -> 소문자
int c = 'A';
c |= ' ';
c; // 'a'

c = 'Z';
c |= ' ';
c; // 'z'

//소문자 -> 대문자
int c = 'a';
c &= '_';
c; // 'A'

int c = 'z';
c &= '_';
c; // 'Z'


// 스위칭
char a = 'A';
char mask = 1 << 5; //0b00010000 을 만든다

a = a ^ mask; // XOR연산처리
printf("%c", a); /* A */

 a = a ^ mask; // XOR연산처리
printf("%c", a); /* a */

 

 

  • bool 값 여러개 보관

int가 32비트이므로 bool값을 32개 넣을수 있다.

#include <bitset>

/* 이렇게 각 아이템 유무 상태들만 정의 */
const unsigned char opt0 = 1 << 0; // 00000001  아이템 0을 가진 상태 정의
const unsigned char opt1 = 1 << 1; // 00000010  아이템 1을 가진 상태 정의
const unsigned char opt2 = 1 << 2; // 00000100  아이템 2을 가진 상태 정의
const unsigned char opt3 = 1 << 3; // 00001000  아이템 3을 가진 상태 정의
const unsigned char opt3 = 1 << 4; // 00010000  아이템 4을 가진 상태 정의
const unsigned char opt3 = 1 << 5; // 00100000  아이템 5을 가진 상태 정의
const unsigned char opt3 = 1 << 6; // 01000000  아이템 6을 가진 상태 정의
const unsigned char opt3 = 1 << 7; // 10000000  아이템 7을 가진 상태 정의

cout << bitset<8>(opt0) << endl; // 00000001 출력
cout << bitset<8>(opt1) << endl; // 00000010 출력
cout << bitset<8>(opt2) << endl; // 00000100 출력 
cout << bitset<8>(opt3) << endl; // 00001000 출력

 

  • 비트 플래그

int가 32비트이므로 bool값을 32개 넣을수 있다.

//아이템을 얻었을 때. (플래그 켜기 : |=  )
items_flag = 0b00000000; // 초기화.
items_flag |= opt0; // 아이템 0 을 얻었다. //0b00000001;
items_flag |= (opt2 | opt3); // 아이템 2와 3 을 얻었다. ((opt2 | opt3)= 0b000001100) 
// 0b00001101 출력


flag = flag | mask; /* 0b01010111 */

// 아이템 3 을 잃었다. (플래그 끄기 : &=~  )
items_flag = 0b00001101; //아이템 0,2,3 있음
items_flag &= ~ opt3; // 아이템 3 을 잃었다. (~opt3 = 0b11110111)
// 0b00000101 출력

//소유 상태 확인( & )
if (items_flag & opt1) //itmes_flag의 아이템 1 자리가 0 이면 false가 나와 가지고 있지 않다고 판명

//해당 아이템 유무 상태를 뒤바꿔주기 (XOR : ^=)
items_flag = 0b00000101;
if ( ( items_flag & opt2 )  && ! ( items_flag & opt1 ) )//아이템 2는 가지고 있고 아이템 1은 가지고 있지 않다면.
{
		items_flag ^= opt1; // 00000111 //아이템1 값이 0이므로 1로 바뀐다. → 00000111
		items_flag ^= opt2; // 00000011 //아이템2 값이 1이므로 0로 바뀐ㄷ. → 00000011
}
 // 00000011 출력

 

 

 

 

  • 색을 표현 RGB 

 1 byte(=8bit) 3개로 표현한다. ( 총 24 bit )

16진수 하나의 수로 4bit 표현 가능

  • 0 ~ 9 → 0000 ~ 1001
  • A → 1010
  • B → 1011
  • C → 1100
  • D → 1101
  • E → 1110
  • F → 1111
  • FF → 11111111

16진수 6개로 색 표현 가능 (16진수 2자리 수로 각각 빨간색, 초록색, 파란색 표현.)

이 3개의 색 조합으로 색을 표현한다.

0x RR GG BB

빨간색 0xFF0000

초록색 0x00FF00

파란색 0x0000FF

0xDAA520 → 11011010 10100101 00100000

빨간색이 DA 정도, 초로색이 A5 정도, 파란색이 20 정도로 섞여있는 색이라는 뜻

 

 

 

 

관련글 더보기