비트 마스킹,비트연산으로 비트 가지고 놀기 이진수를 이용한 꼼수

2022. 1. 17. 20:55·이전자료/웹개발

 

이진수가 특히 좋은 점 이진수로 굉장히 많은 꼼수가 가능한 이유는 간단하기 때문이다.

한자리 숫자가 0,1이기 때문에 굉장히 재미있는 걸 많이 할 수 있다.

 

비트 연산

여기의 코드가 한 줄 있다.

int a;
 

이 번수 a에 어떤 값이 들어 있는지 모른다.

이 변수와 비트 연산만 이용해서 변수의 값을 0으로 초기화할 수 있을까?

 

어차피 비트 연산은 몇개 없으니 다 해보면된다.

모르면 일단 해보면서 보고 그 관찰한 결과가 왜 나오는지 고민하면 된다.

 

변수 a의 하위 8비트의 값이 '0101 1010'이라 가정한다.

 

어떤 비트 연산을 하면 a의 값이 0이 될까?

a = a ? a;
 

xor 같은 숫자 면 모두 0이 된다.

일반적으로 a = 0 보다 a = a ^ a이 성능이 더 빠르다.

성능이 중요한 임베디드 시스템에서 자주 쓰던 꼼수

아직도 똑똑한 컴파일러는 XOR 연산으로 바꿔주기도 함.

a = 0를 보는 순간 a = a ^ a로 바꾼다는 의미이다.

 

여기에 두 정수가 있다.

int a = 3;
int b = 112;
 

한 가지 비트 연산자를 세 번 쓰면 서로의 값을 바꿀 수 있다.

과연 어떤 연산자 일까?

스왑같은개념이라고 보면된다.

a = a ^ b;
b = a ^ b;
a = a ^ b;
 

정답은 XOR

촉으로도 가능한데

NOT은 하나만 받기 때문에 패스

두 변수를 아무리 AND / OR 해봐야 값이 변하지 않음

하나 남은 것 XOR 밖에 없다.

 

비트마스킹

https://icarus.cs.weber.edu/~dab/cs1410/textbook/2.Core/bitops.html

 

if (num % 2 == 0) //짝수
if (num % 2 == 1) //홀수
if (num % 2 != 0) //홀수 좀더 나은방법
 

홀수 더 좋은 방법은

 

컴퓨터에서 0이랑 비교할 수 있으면 비교하는 게 무조건 좋다.

비트 연산으로 짝수/홀수 판별하기

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

위의 값이 뭐든 간에 0x1을 해서 0인지 1인지 알 수 있다.

앞에 0으로 세팅을 해놨기 때문에 앞에는 모두 0으로 들어온다.

이걸 마스킹이라고 한다. 즉 앞에는 0으로 다 가렸다.

이렇듯 필요한 피트만 추출하는 방식 비트 마스킹이라고 한다.

 

mask : 가리다, 가면

 

비트플래그

불리언 형의 1,0을 flag라고 한다.

이런 걸 여러 개 모아놓을 수 있다.

불리언 하나면 4바이트씩 먹는다. 근데 0, 1만 있으면서 왜 4바이트씩이나 먹냐?

1비트 형 자료형은 없으니깐 8개를 모아서 1바이트로 쓴다.

32개를 모아서 int형으로 써줄게 그러면 int형 하나에 32개의 불리언을 쓸 수가 있다.

32개 변수를 쓰는 것보다 용량이 작다는 장점이 있다.

 

특정 플래그를 켜는 방법

플래그 = 플래그 | 마스크;

 

기존의 비트는 다 유지되면서 켜려는 or을 통해서 1이 되게 만들어준다.

 

특정 플래그를 끄는 방법

 

플래그 = 플래그 & ~마스크;

 

특정 플래그를 토글 하는 방법

 

플래그 = 플래그 ^ 마스크;

 

토글이란 켜진 상태(on) 라면 끄고(off)

 

꺼진 상태(off) 라면 켜는(on) 행위

 

비트 플래그 예

        final byte ATTACK_NONE = 0;
        final byte ATTACK_FIRE = 1;
        final byte ATTACK_ICE = 2;
        final byte ATTACK_WIND = 3;
        final byte ATTACK_ARCANE = 4;
        final byte ATTACK_SIZE = 5;

        byte propertyFlags = 8; //외부에서 받은값
        System.out.printf("0%s\n", Integer.toBinaryString(propertyFlags));

        byte mask1 = (byte) ((1 << ATTACK_FIRE) | (1 << ATTACK_ARCANE));
        propertyFlags |= mask1; //화속성, 비전속성 켬
        System.out.println(Integer.toBinaryString(propertyFlags));

        byte mask2 = (byte) (1 << ATTACK_ICE);
        propertyFlags ^= mask2; // 빙속성 토글
        System.out.println(Integer.toBinaryString(propertyFlags));

        byte mask3 = (byte) (1 << ATTACK_WIND);
        propertyFlags &= (byte) ~mask3; // 풍속성 끔
        System.out.println(Integer.toBinaryString(propertyFlags));
 

결과

사진 삭제

사진 설명을 입력하세요.

비트 마스킹 대소문자 변환

        char c = 98;
        char mask1 = 0x20;
        if (c >= 'a' && c <= 'z') {
            c = (char) (c ^ mask1);
        }
 

다른 방식의 비트 마스킹 대소문자 변환방법

    static void BitMasking(){
        char c1 = 'A';
        if(isAlphabet(c1)){
            c1 = (char) (c1 | mask1);
        }
        if(isAlphabet(c1)){
            c1 = (char) (c1 &~ mask1);
        }
    }
    static boolean isAlphabet(char alphabet){
        return Pattern.matches("^[a-zA-Z]*$",Character.toString(alphabet));
    }
 

비트 마스킹 2의 승수 판별하기

어떤 수가 2의 승수인지를 어떻게 판단할까?

2의 승수는 2로만 계속 곱한 수

    static boolean isPower(int n){
        while (n != 1) {

            if (n % 2 != 0) {
                return false;
            }

            n = n / 2;

        }
        return true;
    }
 

계속 2로 나눠서 나머지가 0이 아니면 2의 승수가 아니다.

        byte a = 0b1010;

        if(a == (a & -a)){
            System.out.println("2의 거듭제곱이다.");
        }else{
            System.out.println("2의 거듭제곱이 아니다.");
        }
 

a를 2의 보수를 하게 되면 -a가 된다.

그리고 a & -a를 하게 되면 2의 거듭제곱은 a와 동일하다.

1000 > 0111 + 1 > 1000 == 1000

하지만 2의 거듭제곱을 하지 않은 수는 동일하지 않다.

1010 > 0101 + 1 > 0110 != 1010

'이전자료 > 웹개발' 카테고리의 다른 글

node.js(express) .env로 DB정보 따로 관리하기  (0) 2022.01.17
프로그래밍에서 논리란?  (0) 2022.01.17
웹개발을 위한 XAMPP 설치 방법 [PHP 코딩 서버 아파치]  (0) 2022.01.17
구글 크롬 플래시중단, 플래시대체 파일 업로드 테스트 방법  (0) 2022.01.17
웹개발을 위한 XAMPP 설치 방법 [PHP 코딩 서버 아파치]  (0) 2021.08.15
'이전자료/웹개발' 카테고리의 다른 글
  • node.js(express) .env로 DB정보 따로 관리하기
  • 프로그래밍에서 논리란?
  • 웹개발을 위한 XAMPP 설치 방법 [PHP 코딩 서버 아파치]
  • 구글 크롬 플래시중단, 플래시대체 파일 업로드 테스트 방법
나의 로그
나의 로그
안녕하세요
  • 나의 로그
    Log
    나의 로그
  • 전체
    오늘
    어제
    • 분류 전체보기 (26)
      • 실무 (0)
        • 코인거래소 (0)
      • 개인공부 (2)
        • TIL (2)
      • 이전자료 (24)
        • 웹개발 (16)
        • 서버 (7)
        • 프로그램 (1)
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
나의 로그
비트 마스킹,비트연산으로 비트 가지고 놀기 이진수를 이용한 꼼수
상단으로

티스토리툴바