우리가 일반적으로 사용하는 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 까지 표현 가능
더해서 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)를 넣어줌
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 위의 방식과 플로우는 같지만 Or 연산을 사용
나머지 인덱스는 그대로 두고 해당 비트만 0으로 설정하고 싶다면
-> 이 경우엔 해당 자릿수만 0이고 나머지는 1인 값과 AND 연산을 하면 될것
-> xxxx & 0111 -> 0xxx
0111은 어떻게 만들까?
-> 앞서 1000과 정 반대
-> 즉 1 << 3에다가 ~(not)연산을 진행하면 됨!
static int clearBit(int num, int index){
return num & ~(1 << index);
}
빼기의 결과가 NOT과 같음-> 하지만 여기선 빼기 연산 사용
NOT을 할 경우에는 앞의 값들도 다 1로 바뀌지만 -1을 한 경우에는 뒤에 값들만 1로 바뀜!
static int clearLeftBits(int num, int index){
return num & ((1 << index) - 1);
}
모든 비트가 1은 숫자는 -1
-> 이를 index+1 만큼 좌쉬프트 해준다면 원하는 1110000과 같이 원하는 값이 나올것
-> 찾아낸 값과 원래 값 AND 연산
static int clearRightBits(int num, int index){
return num & (-1 << (index+1));
}
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
}
}