[자바/기초] 비트 연산자와 시프트 연산자

2진법

- 0과 1, 두 개의 숫자만으로 수를 표현하는 방법으로써, 컴퓨터에서 데이터 표현에 사용된다.

- 2진법은 자릿값이 올라갈 수록 그 크기가 2배씩 커지게 된다.

10진수 0 1 2 3 4 5 6 7 8 9 10
2진수 0 1 10 11 100 101 110 111 1000 1001 1010

보수 (Complement)

- 사전적 의미로는, 보충해주는 수를 의미하며, 각 자리의 숫자의 합이 어느 일정한 수가 되게 하는 수를 말한다.

- "십진수 7의 10의 보수는 3"과 같이 10이 되기 위해 보충해주는 수를 의미한다.

1의 보수 ( 1's Complement )

- 총 n개의 비트로 정수를 표현할 때, 모든 n비트가 1로 이루어진 수에서 표현하고 싶은 음수의 절댓값을 뺀 수가 바로 1의 보수 방법으로 표현한 음수가 된다.

- 어떤 음수를 1의 보수 방법으로 표현하고 싶다면 그 음수의 절대값의 모든 비트 숫자들을 반전시키면 된다.(0 은 1로 반전, 1은 0으로 반전) 이 성질 덕분에 1의 보수 방법에서는 2진수 연산값이 실제 값과 같다.

- "10진수 5의 1의 보수는 011"이다.

2의 보수 ( 2's Complement )

- 총 n개의 비트로 정수를 표현할 때, 2n = 1000...0(2) 에서 표현하고 싶은 음수의 절댓값을 뺀 수가 바로 2의 보수 방법으로 표현한 음수가 된다.

- 어떤 음수를 2의 보수 방법으로 표현하고 싶다면 그 음수의 절대값의 모든 비트 숫자들을 반전시킨 후에 (0 은 1로 반전, 1은 0으로 반전) 1을 더하면 된다.

- "10진수 5의 2의 보수는 101"이다.

비트 연산자와 시프트 연산자

- 두 연산자 모두 비트 단위로 연산을 수행한다.

비트 연산자

연산자 의미 설명
&   논리곱(AND)   두 비트 모두 1일 때만 1
|   논리합(OR)   두 비트 중 한 개만 1 이면 1
^   배타적 논리합(XOR)   두  비트의 값이 다르면 1
~   부정(NOT)   비트 반전

- 논리 연산자와 동작은 유사하지만, 논리 연산자와는 달리 각각 연산자의 기호는 한 개만 사용한다.

- 두 개의 비트를 각각의 비트 연산자를 수행한 결과를 표현하면 아래의 도표와 같이 나타낼 수 있다.

A B A & B A | B A ^ B ~A
0 0 0 0 0 1
0 1 0 1 1 X
1 0 0 1 1 X
1 1 1 1 0 0

자바에서의 비트 연산 사용 방법

public class BitOperator {
	public static void main(String[] args) {
    	// 정수를 바이너리(2진수)로 나타내는 방법
        // int 형의 Wrapper 클래스인 Integer의 내장 함수를 사용한 표현
        System.out.println(Integer.toBinaryString(2));  // 10
        // 출력할 때, 바이너리 값으로 변경 후 원하는 글자수만큼 0으로 채워서 표현
        System.out.print("%04d\n", Integer.toBinaryString(2)));    // 0010
    	
    	// 논리곱(AND) 연산
    	System.out.println("2 & 7 = " + (2 & 7));    // 2
        System.out.println("010 & 111 = " + (0b010 & 0b111));    // 2
        
    	// 논리합(OR) 연산
    	System.out.println("2 | 7 = " + (2 | 7));    // 7
        System.out.println("010 & 111 = " + (0b010 | 0b111));    // 7
        
    	// 배타적 논리합(XOR) 연산
    	System.out.println("2 ^ 7 = " + (2 ^ 7));    // 5
        System.out.println("010 ^ 111 = " + (0b010 ^ 0b111));    // 5
        
        
    	// 부정(NOT) 연산
    	System.out.println("~2 = " + (~2));    // -3
        System.out.println("~010 = " + ~0b010);    // -3
    }
}

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

연산자 설명
x<<y   정수 x의 각 비트를 y만큼 왼쪽으로 이동시킨다. (빈 자리는 0으로 채워진다.)
x>>y   정수 y의 각 비트를 오른쪽으로 이동시킨다. (빈 자리는 정수의 최상위 비트로 채워진다.)
x>>>y   정수 x의 각 비트를 y만큼 오른쪽으로 이동시킨다. (빈 자리는 0으로 채워진다.)

- 비트를 좌우로 이동시키는 기능을 하는 연산자이다.

- 데이터 암호화 작업이나 IOT와 같은 전자 기기 제어 작업 등에 많이 사용된다.

자바에서의 시프트 연산 사용 방법

public class ShiftOperator {
	public static void main(String[] args) {
    	int number = 2;
    
    	// << 연산자
        System.out.println("2 << 7 = " + (2 << 7));    // -256
    
    	// >> 연산자
        System.out.println("7 >> 2 = " + (7 >> 2));    // 1
        System.out.println("-7 >> 2 = " + (-7 >> 2));    // -2
    
    	// >>> 연산자
        System.out.println("14 >>> 2 = " + (14 >>> 2));    // 3
        System.out.println("-14 >>> 2 = " + (-14 >>> 2));    // 1073741820
    }
}

⊙ 참고 문헌

  1. 이병승, 「초보 개발자를 위한 자바:한 권으로 배우는 자바 마스터 가이드 북」, 영진닷컴, 2024, p1375 - 1380
  2. 마종현, 「제로베이스 백엔드 취업 파트타임 스쿨 5기:Part 01. Java 기초-Chapter 01. Java 프로그래밍-03.여러가지 연산자」, 제로베이스, 2024, https://zero-base.co.kr/
  3. 나무위키, 「컴퓨터에서의 수 표현:2.컴퓨터에서 정수 표현하기:2.2. 표현법」, 나무위키 , 2024.07.11, https://namu.wiki/w/컴퓨터에서의%20수%20표현s-2.2