본문 바로가기

Java SE Tutorials/Bitwise Operators

Java Bit Operators

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