비트 연산 완전 정복

WOOK JONG KIM·2023년 3월 22일
0

궁금 저장소

목록 보기
5/5
post-thumbnail

우리가 일반적으로 사용하는 Integer를 생각해보자
-> 우리가 이를 컴퓨터에 저장하면 비트로(0,1)저장이 됨

1byte -> 8bit

Integer의 경우 총 32개의 공간에 데이터(0,1)가 담김

int i = 8을 저장했다고 가정 시

8저장후 앞의 나머지는 0으로 채워짐

4bytes -> 32 bits -> 2^32

32개의 공간으로 표현할수있는 최대 수(공간에 데이터를 다 1로 셋팅했을떄)
-> 단순 계산하면 2^32개의 숫자를 표현할 수 있지만 0부터 시작하기 때문에 표현할 수 있는 최대 숫자의 크기는 2^32 - 1(0부터 32까지의 공간밖에 없음)
-> 즉 0~32까지의 공간이 있다 가정하고, 10000.....0000 으로 되어있다 생각했을 때 거기서 1을 빼면 0~31공간에 111......111을 채워넣은 값과 같음

정수엔 양의 정수와 음의 정수가 있기에 맨 앞에 칸은 부호를 표현하기 위해 사용!
-> 부호를 나타내는 앞의 공간을 빼고 생각했을 떄, 0~30 공간에서 나온 수로 양의 정수와 음의 정수 표현
-> 음의 정수일떄는 뺴기 1을 안해줘도됨(양수에서 0을 표현했기에 음수에서는 표현할 필요가 없음)

-1이 음의 숫자중에서는 가장 큰 숫자이기에 앞에 부호1, 뒤에 남은 칸에 다 1이 삽입되어있음
-> 음의 수에 경우 표현할 수 있는 가장 작은 값이 앞에 부호1, 뒤에 남은 칸이 다 0으로 된경우

Integer의 경우 -2147483648 ~ 2147483647 까지 표현 가능


Bit Operation

더해서 2가 되면 다음 자릿수 한칸 올림(2진수 더하기)

OR 연산 해보기

두개 중에 하나라도 1이면 결과는 1
-> AND 연산은 둘다 1이여야 1
-> xxxx라는 값이 있을때 1111과 AND 연산을 하면 무조건 자기 자신이 나옴

NOT연산은 비트를 거꾸로 바꾸기
-> ex) ~0101 -> 1010

XOR 연산은 두개가 같으면 0, 다르면 1
-> 예를 들어 xxxx 라는 값이 있을 때 이를 0000과 xor 연산하면 무조건 자기 자신이 나옴
-> xxxx와 1111과 연산하면 결과는 무조건 ~xxxx가 결과로 나옴
-> xxxx와 xxxx를 xor 연산하면 무조건 0000

좌 시프트의 경우 왼쪽으로 밀고, 빈 공간은 0으로 채워주면 됨

쉬프트 방법에는 부호 비트를 고려해서 시프트 하는 방법과, 고려하지 않고 시프트 하는 방법이 있음

고려하지 않고 하였을때(>>>)

옮긴후 왼쪽에 비트는 0으로 채움
-> 이렇게 부호와 상관없이 모든 비트를 오른쪽으로 옮기는 것을 logical right shift( >>> )라고 함

고려하여 시프트 하는 경우(>>)

옮기는 방법은 같으나 맨앞의 빈칸에 0대신 부호(0,1)를 넣어줌


코드 예시(getBit)

int num = 9; // 1001

// 위의 값에서 4번째(1)에 해당 하는 비트 값을 받아오기
int index = 3;

예를들어 숫자 9의 경우의 3번 인덱스의 값은 1
-> 20인 경우엔 3번인덱스 값이 0
-> 다른 데이터에 나머지 자리는 다 0으로 만들고 해당 자릿수의 대한 값만 원본 데이터에서 받아온 값을 만듬
-> 그 값이 0이라면 해당 자리가 0인것이고 아니면 1

어떤 연산을 해야 해당 자리에 값 빼고 나머지를 다 0으로 만들수 있을까?
-> 위 경우 ?부분 즉, 해당 자릿수에 값만 1로 설정한뒤 AND 연산을 진행하면 됨
-> xxxx & 1000

이때 1000 처럼 해당 자리수가 1이고, 나머지가 0인 값은 어떻게 만들까?

1을 알고자 하는 해당 index 값 만큼 좌시프트 하면 됨!

정리

public class Main {
    static boolean getBit(int num, int index){
        return (num & (1 << index)) != 0; // 1이면 true 0이면 false
    }
    public static void main(String[] args) throws IOException{
        System.out.println(getBit(9,3)); // 1 0 0 1
        System.out.println(getBit(5,3)); // 0 1 0 1
    }
}

SetBit, ClearBit

SetBit 위의 방식과 플로우는 같지만 Or 연산을 사용

나머지 인덱스는 그대로 두고 해당 비트만 0으로 설정하고 싶다면
-> 이 경우엔 해당 자릿수만 0이고 나머지는 1인 값과 AND 연산을 하면 될것
-> xxxx & 0111 -> 0xxx

0111은 어떻게 만들까?
-> 앞서 1000과 정 반대
-> 즉 1 << 3에다가 ~(not)연산을 진행하면 됨!

static int clearBit(int num, int index){
        return num & ~(1 << index);
}

ClearLeftBits

빼기의 결과가 NOT과 같음-> 하지만 여기선 빼기 연산 사용

NOT을 할 경우에는 앞의 값들도 다 1로 바뀌지만 -1을 한 경우에는 뒤에 값들만 1로 바뀜!

static int clearLeftBits(int num, int index){
        return num & ((1 << index) - 1); 
}

ClearRightBits

모든 비트가 1은 숫자는 -1
-> 이를 index+1 만큼 좌쉬프트 해준다면 원하는 1110000과 같이 원하는 값이 나올것
-> 찾아낸 값과 원래 값 AND 연산

static int clearRightBits(int num, int index){
        return num & (-1 << (index+1));
}

UpdateBit

public class Main {
    static int updateBits(int num, int index, boolean val){
        return (num & ~(1 << index)) | ((val? 1: 0) << index);
    }
    public static void main(String[] args) throws IOException{
        System.out.println(updateBits(169,3,false)); //161
    }
}

profile
Journey for Backend Developer

0개의 댓글