본문 바로가기

Language/Java

Java~비트 연산자

반응형

시작에 앞서

연산자는 크게 '단항', '이항', '삼항' 연산자로 나누어집니다. 이렇게 구분하는 기준은 연산을 하는 대상이되는 피연산자의 갯수입니다. 예를 들면 피연산자가 하나인 연산을 위해 사용되는 연산자를 단항 연산자라 부릅니다.

이항연산자에는 산술, 비교, 논리 연산자 등이 있습니다만, 개인적으로 필자의 실무에 있어서, 다른 연산자에 비해 비트 연산자를 다룬 경험이 적은 것 같습니다. 잊지 않도록 이번 기회에 한번 정리해 봅시다.

비트 연산자

비트연산자는 0과 1로 이루어진 비트(bit)의 연산에 사용되는 연산자입니다. 비트 연산자는 크게 '비트 논리 연산자'와 '비트 이동 연산자'로 나누어집니다. 하나씩 예제와 함께 확인해 보도록 합시다.

1. 비트 논리 연산자

비트 논리 연산자로는 &(and), |(or), ^(xor), ~(not) 네 종류로 나누어 집니다.

&(and)

&는 and 연산자로, 피연산자 양쪽 모두 1일 경우 1을 반환, 그 외의 경우에는 0을 반환합니다.
예제를 하나 확인해 봅시다.

int test1 = 8;
int test2 = 10;

// toBinaryString를 이용하면 10진수의 숫자를 2진수로 반환 할 수 있습니다.
// 예제에 사용할 정수의 2진수 형태를 확인 해 봅시다.
System.out.println(Integer.toBinaryString(test1)); // 출력: 1000
System.out.println(Integer.toBinaryString(test2)); // 출력: 1010

// & 연산자를 이용해 봅시다
int result = test1 & test2;

// 결과 확인
System.out.println(result); // 출력: 8
System.out.println(Integer.toBinaryString(result)); // 출력: 1000
피연산자 2³ 2⁰
test1 1 0 0 0
test2 1 0 1 0
피연산자 비교 양쪽 모두 1 양쪽 모두 0 0과 1로 양쪽이 다름 양쪽 모두 0
결과 출력 1 0 0 0

양쪽 모두 같은 숫자라도, 1의 경우만 1을 반환합니다. 그렇기 때문에 1을 반환 하는 것은 2³자리 뿐입니다.

|(or)

|은 or 연산자로, 피연산자 중 한 쪽만 1일 경우 1을 반환, 그 외의 경우에는 0을 반환합니다.

int test1 = 8; // 1000
int test2 = 10; // 1010

// | 연산자를 이용해 봅시다
int result = test1 | test2;

// 결과 확인
System.out.println(result); // 출력: 10
System.out.println(Integer.toBinaryString(result)); // 출력: 1010
피연산자 2³ 2⁰
test1 1 0 0 0
test2 1 0 1 0
피연산자 비교 양쪽 모두 1 양쪽 모두 0 0과 1로 양쪽이 다름 양쪽 모두 0
결과 출력 1 0 1 0

양쪽 다 1인 2³자리, 한 쪽이 1인 2¹자리가 1을 반환 하기 때문에 10(1010)의 결과가 나옵니다.

^(xor)

^은 xor연산자로, 피연산자 중 한 쪽이 1이고 다른 한 쪽이 0인 경우 1을 반환, 그 외의 경우에는 0을 반환합니다.

int test1 = 8; // 1000
int test2 = 10; // 1010

// ^ 연산자를 이용해 봅시다
int result = test1 ^ test2;

// 결과 확인
System.out.println(result); // 출력: 2
System.out.println(Integer.toBinaryString(result)); // 출력: 10
피연산자 2³ 2⁰
test1 1 0 0 0
test2 1 0 1 0
피연산자 비교 양쪽 모두 1 양쪽 모두 0 0과 1로 양쪽이 다름 양쪽 모두 0
결과 출력 0 0 1 0

양쪽이 서로 다른 자리는 2¹자리밖에 없기 때문에, 2(0010)의 결과가 나옵니다.

~(not)

~은 not연산자로, 댜른 연산자와 달리 피연산자가 하나입니다. 0은 1로, 1은 0으로 반대를 반환합니다.

int test = 10; // 1010

// ~ 연산자를 이용해 봅시다
int result = ~test;

// 결과 확인
System.out.println(result); // 출력: -11
System.out.println(Integer.toBinaryString(result)); // 출력: 11111111111111111111111111110101

이진수(binary)로 출력했을 때, 앞의 &(and), |(or), ^(xor)의 다른 연산자들과 달리 조금 긴 결과값이 나옵니다.
int는 32비트의 숫자로 모든 자리가 반전된 결과가 출력되게 되는 가운데, 이 중, 가장 좌측에 있는 숫자는 기호를 표시합니다. 1일 경우엔 음수(-), 0인 경우엔 양수(+, 생략가능)가 됩니다.

피연산자 기호(2³¹) 2³⁰~2⁴ 2³ 2⁰
test 0 0~ 1 0 1 0
결과 출력 1 1~ 0 1 0 1

2. 비트 이동(시프트) 연산자

비트 이동(시프트) 연산자로는 <<, >>(기호 있음), >>>(기호 없음) 세 종류가 있습니다.

피연산자 << n
피연산자 >> n
피연산자 >>> n

각 연산자는 n회 만큼 화살표의 방향으로 비트를 이동하는 연산을 합니다.
예를 한번 살펴 봅시다.
먼저, 좌측으로 이동하는 '<<'를 살펴 봅시다.

int test = 13;
System.out.println(Integer.toBinaryString(test)); //...001101

//좌측으로 2회 이동
test  = test << 2;
System.out.println(test); //52
System.out.println(Integer.toBinaryString(test)); //...110100
피연산자 2³⁰~2⁶ 2⁵ 2⁴ 2³ 2⁰
13 0~ 0 0 1 1 0 1
52 0~ 1 1 0 1 0 0

2³~2⁰의 1101이 좌측으로 2회 이동하여 2⁵~2²에 위치하게 되어, 52의 결과값이 나옵니다.
우측으로 이동하는 다른 연산자도 살펴봅시다.

int test = 52;
System.out.println(Integer.toBinaryString(test)); //...110100

// >>(기호 있음)
int test1  = test >> 2;
System.out.println(test1); //13
System.out.println(Integer.toBinaryString(test1)); //...001101

// >>>(기호 없음)
int test2  = test >>> 2;
System.out.println(test2); //13
System.out.println(Integer.toBinaryString(test2)); //...001101
피연산자 기호(2³¹) 2³⁰~2⁶ 2⁵ 2⁴ 2³ 2⁰
52 0 0~ 1 1 0 1 0 0
13 0 0~ 0 0 1 1 0 1

상기의 '<<'와는 반대로,
2³~2⁰의 110100이 우측으로 2회 이동하여 2⁵~2²에 위치하게 되어, 13의 결과값이 나옵니다.

int test = -52;
System.out.println(Integer.toBinaryString(test)); //11111111111111111111111111001100

// >>(기호 있음)
int test1  = test >> 2;
System.out.println(test1); //-13
System.out.println(Integer.toBinaryString(test1)); //11111111111111111111111111110011

//>>>(기호 없음)
int test2  = test >>> 2;
System.out.println(test2); //1073741811
System.out.println(Integer.toBinaryString(test2)); //111111111111111111111111110011
피연산자 기호(2³¹) 2³⁰~2⁶ 2⁵ 2⁴ 2³ 2⁰
-52 1 1~ 1 1 0 1 0 0
-13 1 1~ 0 0 1 1 0 1
1073741811 - 1~ 0 0 1 1 0 1

'>>'와 '>>>'의 차이는 연산 후 결과값의 기호의 유무입니다.
두 연산자 모두 2회 우측으로 이동합니다만, '>>>'는 기호(2³¹)자리의 값이 없으므로,
111111111111111111111111110011(십진법 수, 1073741811)의 결과값이 나오게 됩니다.

반응형