Java 프로그래밍, 비트 연산자 ( ~, &, |, ^, >>, <<, >>> )
비트관련 연산자들은 모두 정수형 데이터에 적용되어 데이터를 구성하는 비트를 좌우로 이동하거나 비트의 값을 변경하거나 비트의 내용을 비교할 때 사용된다. 특수한 목적으로는 사용되지만 일반적인 응용 프로그램을 작성할 때 사용하는 경우는 드물다
단항 비트 반전 연산자 ( Bit Inversion Operator, Bit Complement ) : ~
정수 데이터를 구성하는 비트를 반전한다. 0->1, 1->0 으로 변경한다
비트 반전 연산자를 이용한 컴퓨터의 음수표현에 대한 이해
public class Tutorials { public static void main(String[] args) { // 컴퓨터의 음수 표현에 대한 이해 // 부호비트를 포함하여 모든 비트를 0으로 셋트하면 0을 의미한다 // 부호비트를 포함하여 모든 비트를 1로 셋트하면 음수의 시작인 -1이 된다 // 위와 같은 이유로 양수의 모든 비트를 반전하는 것만으로는 음수가 안된다 // 양수의 비트를 모두 반전하고 +1을 하면 음수가 된다 int n = 0; // 32개 비트가 모두 0으로 셋트됨(0) int n2 = ~n; // 32개 비트 모두 1로 셋트됨(-1) System.out.printf("%d의 음수 = %d %n", n, n2+1); // 0 n = 10; n2 = ~n+1; System.out.printf("%d의 음수 = %d %n", n, n2); // -10 } }
비트 AND 연산자 ( Bitwise AND Operator ) : &
비트의 값을 대상으로 AND 연산을 한다.
비트 OR 연산자 ( Bitwise OR Operator ) : |
비트의 값을 대상으로 OR 연산을 수행한다
비트 배타적 OR 연산자 ( Bitwise Exclusive OR Operator ) : ^
OR 연산 중에서 연산대상의 비트가 둘다 1인 경우에는 0을 리턴한다
비트 이동 연산자 ( Bit Shift Operator ) : Signed Right Shift >>, Signed Left Shift <<, Unsigned Right Shift >>>
비트 연산자 사용 예
public class Tutorials { public static void main(String[] args) { System.out.printf("0의 비트문자열=%s %n", Integer.toBinaryString(0)); System.out.printf("1의 비트문자열=%s %n", Integer.toBinaryString(1)); System.out.printf("-1의 비트문자열=%s %n", Integer.toBinaryString(-1)); System.out.printf("-2의 비트문자열=%s %n", Integer.toBinaryString(-2)); // int형 메모리 공간의 32개 비트 중에서 31개 비트만 실제 수를 저장할 때 사용된다 int intMax = Integer.MAX_VALUE; // 2^31-1 = 2147483647; System.out.printf("int 최대 값 = %d %n", intMax); // 2147483647 // 변수에 할당된 메모리를 초과하여 값을 저장하는 경우에는 Overflow 현상이 나타남 // Overflow : 저장한계를 초과하면 저장공간에 저장가능한 최저의 수부터 초과된 만큼 새로 할당됨 int intMin = intMax + 1; // int형 최저값(Integer.MIN_VALUE)으로 순환됨(음수) System.out.printf("%d + 1 = %d %n", intMax, intMin); // -2^31 = -2147483648 int n = intMax + 2; // System.out.printf("%d + 2 = %d %n", intMax, n); // -2147483647 // 비트 왼쪽 이동 연산자(<<)를 이용하여 이동할 때는 이동해온 비트가 부호비트도 갱신하게 된다 // 32비트 이동시마다 사라졌던 비트들이 원래의 값으로 회복된다. n = 5; // ~101 int res = n << 1; System.out.printf("%d << 1 = %d %n", n, res); res = n << 28; // 0101~, 부호비트 직전까지 1로 셋트된 비트가 이동해옴. System.out.printf("%d << 28 = %d %n", n, res); res = n << 29; // 101~, 이동해온 비트(1)가 부호비트를 1로 셋트하면서 부호가 변경된다 System.out.printf("%d << 29 = %d %n", n, res);//-1610612736 res = n << 30; // 01~, 이동해온 비트(0)가 부호비트를 0로 셋트하면서 부호가 변경된다 System.out.printf("%d << 30 = %d %n", n, res);//1073741824 res = n << 31; // 1~ 이동해온 비트(1)가 부호비트를 1로 셋트하면서 부호가 변경된다 System.out.printf("%d << 31 = %d %n", n, res);//-2147483648 res = n << 32; // ~101(5), 자리를 떠난 비트들은 32비트 이동시마다 원래의 자리로 순환된다 System.out.printf("%d << 32 = %d %n", n, res);//5 // >> 비트 우측 이동, 우측으로 영역을 벗어난 비트들은 32비트 이동시마다 원래 값으로 회복된다 // 왼쪽의 빈 자리는 부호비트로 채워지므로 부호가 유지된다 n = 1; res = n >> 1; System.out.printf("%d >> 1 = %d %n", n, res); // 0 res = n >> 31; System.out.printf("%d >> 31 = %d %n", n, res); // 0 res = n >> 32; // 우측으로 벗어난 비트들은 다시 원래의 자리로 회복된다 System.out.printf("%d >> 32 = %d %n", n, res); // 1 res = n >> 64; // 우측으로 벗어난 비트들은 다시 원래의 자리로 회복된다 System.out.printf("%d >> 64 = %d %n", n, res); // 1 n = -2; res = n >> 1; // -1 System.out.printf("%d >> 1 = %d %n", n, res); res = n >> 31; // -1 System.out.printf("%d >> 31 = %d %n", n, res); res = n >> 32; // -2, 32비트마다 원래의 자리로 순환된다 System.out.printf("%d >> 32 = %d %n", n, res); // >>> unsigned right shift operator // 부호비트를 가리지 않고 왼쪽의 빈 자리를 무조건 0으로 채우고 32비트 이동시마다 원래 값으로 회복된다 // 음수인 경우에는 부호비트를 포함하여 왼쪽의 빈 자리는 무조건 0으로 채워지므로 음수는 양수로 변경되고 // 32비트 이동시마다 원래의 회복되기 때문에 이 때만 다시 음수가 된다 n = 1; res = n >>> 32; // 자리를 떠난 비트들이 원래의 값으로 회복된다 System.out.printf("%d >>> 32 = %d %n", n, res); // 1 n = -1; res = n >>> 31; //1 System.out.printf("%d >>> 31 = %d %n", n, res); res = n >>> 32; //-1, 원래의 자리로 되돌아 옴 System.out.printf("%d >>> 32 = %d %n", n, res); // -1 } }
위의 코드를 실행한 결과화면
0의 비트문자열=0
1의 비트문자열=1
-1의 비트문자열=11111111111111111111111111111111
-2의 비트문자열=11111111111111111111111111111110
int 최대 값 = 2147483647
2147483647 + 1 = -2147483648
2147483647 + 2 = -2147483647
5 << 1 = 10
5 << 28 = 1342177280
5 << 29 = -1610612736
5 << 30 = 1073741824
5 << 31 = -2147483648
5 << 32 = 5
1 >> 1 = 0
1 >> 31 = 0
1 >> 32 = 1
1 >> 64 = 1
-2 >> 1 = -1
-2 >> 31 = -1
-2 >> 32 = -2
1 >>> 32 = 1
-1 >>> 31 = 1
-1 >>> 32 = -1
1의 비트문자열=1
-1의 비트문자열=11111111111111111111111111111111
-2의 비트문자열=11111111111111111111111111111110
int 최대 값 = 2147483647
2147483647 + 1 = -2147483648
2147483647 + 2 = -2147483647
5 << 1 = 10
5 << 28 = 1342177280
5 << 29 = -1610612736
5 << 30 = 1073741824
5 << 31 = -2147483648
5 << 32 = 5
1 >> 1 = 0
1 >> 31 = 0
1 >> 32 = 1
1 >> 64 = 1
-2 >> 1 = -1
-2 >> 31 = -1
-2 >> 32 = -2
1 >>> 32 = 1
-1 >>> 31 = 1
-1 >>> 32 = -1