본문 바로가기
JAVA

JAVA 비트 연산자, 시프트 연산자 [코딩백과 with JAVA]

by GangDev 2024. 12. 21.

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

Java는 비트 단위로 작업을 수행하는 비트 연산자와 비트를 이동시키는 시프트 연산자를 제공합니다. 이들 연산자는 주로 저수준 프로그래밍, 암호화, 비트 조작 등에서 사용됩니다.

비트 연산자 (Bitwise Operators)

  1. 비트 AND(&)
  2. 비트 OR (|)
  3. 비트 XOR (^)
  4. 비트 NOT (~)

시프트 연산자 (Bit Shift Operators)

  1. 왼쪽 시프트 (<<)
  2. 부호 있는 오른쪽 시프트 (>>)
  3. 부호 없는 오른쪽 시프트 (>>>)

사용 예시:

public class BitwiseAndShiftExample {
    public static void main(String[] args) {
        int x = 10; // 이진수: 1010
        int y = 6;  // 이진수: 0110

        // 비트 연산자
        System.out.println("x & y: " + (x & y));  // 비트 AND: 0010
        System.out.println("x | y: " + (x | y));  // 비트 OR: 1110
        System.out.println("x ^ y: " + (x ^ y));  // 비트 XOR: 1110
        System.out.println("~x: " + (~x));        // 비트 NOT: 11111111111111111111111111110101

        // 시프트 연산자
        int z = 15; // 이진수: 00001111
        System.out.println("z << 1: " + (z << 1));  // 왼쪽 시프트: 00011110
        System.out.println("z >> 1: " + (z >> 1));  // 오른쪽 시프트: 00000111
        System.out.println("z >>> 1: " + (z >>> 1)); // 부호 없는 오른쪽 시프트: 00000111

        // 비트 마스크 사용
        int flags = 0;
        flags |= 1 << 2; // 3번째 비트를 1로 설정
        flags |= 1 << 5; // 6번째 비트를 1로 설정
        System.out.println("Flags: " + Integer.toBinaryString(flags));

        // 비트 마스크로 특정 비트 확인
        boolean isThirdBitSet = (flags & (1 << 2)) != 0;
        System.out.println("Is third bit set? " + isThirdBitSet);
    }
}

출력 결과는 다음과 같습니다:

x & y: 2
x | y: 14
x ^ y: 12
~x: -11
z << 1: 30
z >> 1: 7
z >>> 1: 7
Flags: 100001
Is third bit set? true

비트 연산자의 특징

  1. 비트 AND (&):

    • 두 비트가 모두 1일 때만 결과가 1입니다.
    • 주로 비트 마스크로 사용됩니다.
    • 예: 0x0f (1111)와 0x2222 (0010001000100010)를 AND하면 0x0002 (0010)가 됩니다.
  2. 비트 OR (|):

    • 두 비트 중 하나라도 1이면 결과가 1입니다.
    • 주로 비트 플래그 설정에 사용됩니다.
  3. 비트 XOR (^):

    • 두 비트가 다를 때만 결과가 1입니다.
    • 암호화 알고리즘에서 자주 사용됩ㄴ디ㅏ.
  4. 비트 NOT (~):

    • 각 비트를 반전시킵니다.
    • 부호 있는 정수에서 ~x는 -(x+1)과 동일합니다.

시프트 연산자의 특징

  1. 왼쪽 시프트(<<):

    • 각 비트를 왼쪽으로 이동시킵니다.
    • 비트가 이동한 자리에 0이 채워집니다.
    • 효과적으로 2의 거듭제곱으로 곱하는 것과 같습니다.
  2. 부호 있는 오른쪽 시프트 (>>):

    • 각 비트를 오른쪽으로 이동시킵니다.
    • 부호 비트(가장 왼쪽 비트)가 채워집니다.
    • 음수에서는 1, 양수에서는 0으로 채워집니다.
  3. 부호 없는 오른쪽 시프트 (>>>):

    • 각 비트를 오른쪽으로 이동시킵니다.
    • 항상 0으로 채워집니다.
    • 부호 있는 정수에서 사용 시 부호를 무시합니다.

사용 예시: 비트 마스크

public class BitwiseShiftExample {
    public static void main(String[] args) {
        int x = 10; // 이진수: 1010
        int y = 6;  // 이진수: 0110

        // 비트 AND (&) 특징
        System.out.println("x & y: " + (x & y));  // 비트 AND: 0010
        System.out.println("x & 0x0f: " + (x & 0x0f)); // 비트 마스크 사용: 0000

        // 비트 OR (|) 특징
        System.out.println("x | y: " + (x | y));  // 비트 OR: 1110
        System.out.println("x | 0x0f: " + (x | 0x0f)); // 비트 플래그 설정: 1111

        // 비트 XOR (^) 특징
        System.out.println("x ^ y: " + (x ^ y));  // 비트 XOR: 1100
        System.out.println("x ^ x: " + (x ^ x));  // 동일한 값 XOR: 0000

        // 비트 NOT (~) 특징
        System.out.println("~x: " + (~x));        // 비트 NOT: 11111111111111111111111111110101
        System.out.println("~0: " + (~0));        // 모든 비트 반전: 11111111111111111111111111111111

        // 왼쪽 시프트 (<<) 특징
        int z = 1; // 이진수: 0001
        System.out.println("z << 2: " + (z << 2));  // 왼쪽 시프트: 0100 (4)
        System.out.println("z << 3: " + (z << 3));  // 왼쪽 시프트: 1000 (8)

        // 부호 있는 오른쪽 시프트 (>>) 특징
        int w = -10; // 이진수: 11111111111111111111111111110110
        System.out.println("w >> 1: " + (w >> 1));  // 오른쪽 시프트: -5
        System.out.println("w >> 2: " + (w >> 2));  // 오른쪽 시프트: -3

        // 부호 없는 오른쪽 시프트 (>>>) 특징
        int u = -10; // 이진수: 11111111111111111111111111110110
        System.out.println("u >>> 1: " + (u >>> 1));  // 부호 없는 오른쪽 시프트: 2147483643
        System.out.println("u >>> 2: " + (u >>> 2));  // 부호 없는 오른쪽 시프트: 1073741821

        // 비트 마스크 사용 예시
        int flags = 0;
        flags |= 1 << 2; // 3번째 비트를 1로 설정
        flags |= 1 << 5; // 6번째 비트를 1로 설정
        System.out.println("Flags: " + Integer.toBinaryString(flags));

        // 비트 마스크로 특정 비트 확인
        boolean isThirdBitSet = (flags & (1 << 2)) != 0;
        System.out.println("Is third bit set? " + isThirdBitSet);
    }
}

출력 결과는 다음과 같습니다:

x & y: 2
x & 0x0f: 0
x | y: 14
x | 0x0f: 15
x ^ y: 12
x ^ x: 0
~x: -11
~0: -1
z << 2: 4
z << 3: 8
w >> 1: -5
w >> 2: -3
u >>> 1: 2147483643
u >>> 2: 1073741821
Flags: 100001
Is third bit set? true

주의사항

  1. 사용 빈도:

    • 이 연산자들은 일반적인 프로그래밍에서는 자주 사용되지 않습니다.
    • 주로 저수준 프로그래밍, 시스템 프로그래밍, 특수한 알고리즘 등에서 사용됩니다.
  2. 가독성:

    • 복잡한 비트 조작은 코드의 가독성을 해칠 수 있으므로, 주석을 통해 의도를 명확히 하는 것이 좋습니다.
  3. 성능 최적화:

    • 때로는 비트 연산을 사용하여 성능을 최적화할 수 있지만, 현대의 컴파일러는 이러한 최적화를 자동으로 수행할 수 있으므로, 가독성을 해치지 않는 한 일반적인 연산자를 사용하는 것이 좋습니다.

편히 모아진 글 보시려면 아래 위키독스 링크 >>
https://wikidocs.net/book/17111