비트 연산
참고
bit
- 1자리수의 2진숫자(0 또는 1)를 뜻하는 binary digit의 약어
- 2진수 1자리수에 상당하는 데이터량을 나타내는 정보의 단위
- byte 는 비트가 여러 개 모인 것으로, 8 bit 가 1 byte 이다
비트 연산자
// 논리곱
int a = 170, b = 245;
// a = 1 0 1 0 1 0 1 0
// b = 1 1 1 1 0 1 0 1
// a&b = 1 0 1 0 0 0 0 0
System.out.print("a&b: ");
System.out.println(a&b); // a&b: 160
// 논리합
a = 170; b = 245;
// a = 1 0 1 0 1 0 1 0
// b = 1 1 1 1 0 1 0 1
// a|b = 1 1 1 1 1 1 1 1
System.out.print("a|b: ");
System.out.println(a|b); // a|b: 255
// 배타적 논리합
a = 170; b = 245;
// a = 1 0 1 0 1 0 1 0
// b = 1 1 1 1 0 1 0 1
// a^b = 0 1 0 1 1 1 1 1
System.out.print("a^b: ");
System.out.println(a^b); // a^b: 95
// 1의 보수 표현
a = 170;
// a = 1 0 1 0 1 0 1 0
// ~a = 0 1 0 1 0 1 0 1
System.out.print("~a: ");
System.out.println(~a); // ~a: -171
시프트 연산자
// 왼쪽 시프트 연산자 <<
/**
*
10110010
1011001000
11001000
왼쪽으로 두칸 밀면서, 비게 되는 오른쪽 두칸은 0 으로 채운다.
그런데, 문제는 왼쪽으로 밀면서 기존의 크기를 넘어서기 때문에 왼쪽으로 넘어선 2개의 비트는 삭제된다.
따라서, 10110010 을 왼쪽으로 밀면 왼쪽 두개 비트인 10 은 삭제되고, 오른쪽의 2개 비트는 0으로 채워져
결과값은 11001000 이 된다.
*/
int c = 178;
System.out.println("before << : "+ c); // before << : 178
c = c << 2;
System.out.println(" after << : "+ c); // after << : 712
// 오른쪽 시프트 연산자 >>
/**
*
10110010
1110110010
11101100
오른쪽으로 2비트 이동한후, 비게되는 왼쪽의 2개비트는 1로 채워지고, 오른쪽에서 2비트 넘어간 부분은 삭제된다.
따라서, 10110010 을 오른쪽으로 2비트 시프트하면, 11101100 이 된다.
그런데, 주의할점은, 오른쪽으로 밀면서 왼쪽에 비게되는 비트부분이 무조건 1 로 채워지는 것이 아니라,
밀기전의 최초 첫째자리 값과 동일한 값으로 채워진다는 것이다.
여기에서는 밀기전의 첫째자리값이 1 이었으므로, 1 로 채워진 것이다.
*/
c = 178;
System.out.println("before >> : "+ c); // before >> : 178
c = c >> 2;
System.out.println(" after >> : "+ c); // after >> : 44
// 논리 오른쪽 시프트 연산자 >>>
/**
*
10110010
0010110010
으로 되는 것으로, 역시 오른쪽으로 밀려난 2개 비트 10 은 삭제되고, 비게되는 왼쪽 2비트는 무조건 0으로 채워진다.
따라서 10110010 을 오른쪽으로 논리 시프트 하면, 00101100 이 된다.
*/
c = 178;
System.out.println("before >>> : "+ c); // before >>> : 178
c = c >>> 2;
System.out.println(" after >>> : "+ c); // after >>> : 44
비트 연산 의 활용
- G.771 코덱 커스터마이징
- 대칭형 암호화: ^ 를 두번 연속 사용하면 원래의 값이 나온다 는 성질을 이용
참고
bit
- 1자리수의 2진숫자(0 또는 1)를 뜻하는 binary digit의 약어
- 2진수 1자리수에 상당하는 데이터량을 나타내는 정보의 단위
- byte 는 비트가 여러 개 모인 것으로, 8 bit 가 1 byte 이다
비트 연산자
// 논리곱
int a = 170, b = 245;
// a = 1 0 1 0 1 0 1 0
// b = 1 1 1 1 0 1 0 1
// a&b = 1 0 1 0 0 0 0 0
System.out.print("a&b: ");
System.out.println(a&b); // a&b: 160
// 논리합
a = 170; b = 245;
// a = 1 0 1 0 1 0 1 0
// b = 1 1 1 1 0 1 0 1
// a|b = 1 1 1 1 1 1 1 1
System.out.print("a|b: ");
System.out.println(a|b); // a|b: 255
// 배타적 논리합
a = 170; b = 245;
// a = 1 0 1 0 1 0 1 0
// b = 1 1 1 1 0 1 0 1
// a^b = 0 1 0 1 1 1 1 1
System.out.print("a^b: ");
System.out.println(a^b); // a^b: 95
// 1의 보수 표현
a = 170;
// a = 1 0 1 0 1 0 1 0
// ~a = 0 1 0 1 0 1 0 1
System.out.print("~a: ");
System.out.println(~a); // ~a: -171
시프트 연산자
// 왼쪽 시프트 연산자 <<
/**
*
10110010
1011001000
11001000
왼쪽으로 두칸 밀면서, 비게 되는 오른쪽 두칸은 0 으로 채운다.
그런데, 문제는 왼쪽으로 밀면서 기존의 크기를 넘어서기 때문에 왼쪽으로 넘어선 2개의 비트는 삭제된다.
따라서, 10110010 을 왼쪽으로 밀면 왼쪽 두개 비트인 10 은 삭제되고, 오른쪽의 2개 비트는 0으로 채워져
결과값은 11001000 이 된다.
*/
int c = 178;
System.out.println("before << : "+ c); // before << : 178
c = c << 2;
System.out.println(" after << : "+ c); // after << : 712
// 오른쪽 시프트 연산자 >>
/**
*
10110010
1110110010
11101100
오른쪽으로 2비트 이동한후, 비게되는 왼쪽의 2개비트는 1로 채워지고, 오른쪽에서 2비트 넘어간 부분은 삭제된다.
따라서, 10110010 을 오른쪽으로 2비트 시프트하면, 11101100 이 된다.
그런데, 주의할점은, 오른쪽으로 밀면서 왼쪽에 비게되는 비트부분이 무조건 1 로 채워지는 것이 아니라,
밀기전의 최초 첫째자리 값과 동일한 값으로 채워진다는 것이다.
여기에서는 밀기전의 첫째자리값이 1 이었으므로, 1 로 채워진 것이다.
*/
c = 178;
System.out.println("before >> : "+ c); // before >> : 178
c = c >> 2;
System.out.println(" after >> : "+ c); // after >> : 44
// 논리 오른쪽 시프트 연산자 >>>
/**
*
10110010
0010110010
으로 되는 것으로, 역시 오른쪽으로 밀려난 2개 비트 10 은 삭제되고, 비게되는 왼쪽 2비트는 무조건 0으로 채워진다.
따라서 10110010 을 오른쪽으로 논리 시프트 하면, 00101100 이 된다.
*/
c = 178;
System.out.println("before >>> : "+ c); // before >>> : 178
c = c >>> 2;
System.out.println(" after >>> : "+ c); // after >>> : 44
비트 연산 의 활용
- G.771 코덱 커스터마이징
- 대칭형 암호화: ^ 를 두번 연속 사용하면 원래의 값이 나온다 는 성질을 이용