1. 비트 왼쪽 시프트

Java에는 3개의 비트 시프트 연산자 도 있습니다 . 실제로 필요한 경우 숫자의 모든 비트를 여러 위치에서 왼쪽 또는 오른쪽으로 매우 간단하게 이동할 수 있습니다.

숫자의 비트를 왼쪽으로 이동하려면 비트 왼쪽 이동 연산자 가 필요합니다 . 다음과 같이 작성되었습니다.

a << b

여기서 a는 비트가 이동되는 숫자이고, 는 해당 숫자의 비트를 왼쪽으로 b몇 번 이동할 것인지를 나타내는 숫자입니다 . a이 작업 중에 오른쪽에 추가된 하위 비트는 0입니다.

예:

결과
0b00000011 << 1
0b00000110
0b00000011 << 2
0b00001100
0b00000011 << 5
0b01100000
0b00000011 << 20
0b001100000000000000000000

한 자리를 왼쪽으로 이동하면 숫자에 2를 곱한 것과 같은 효과가 있습니다.

숫자에 16을 곱하고 싶습니까? 16은 24 와 같습니다 . 따라서 숫자 4자리를 왼쪽으로 이동합니다.


2. 비트 오른쪽으로 이동

비트를 오른쪽으로 이동할 수도 있습니다. 이렇게 하려면 비트 오른쪽 시프트 연산자 를 사용하십시오 . 다음과 같이 작성되었습니다.

a >> b

여기서 a는 비트가 이동되는 숫자이고 는 해당 숫자의 비트를 오른쪽으로 b이동하는 횟수입니다 .a

예:

결과
0b11000011 >> 1
0b01100001
0b11000011 >> 2
0b00110000
0b11000011 >> 5
0b00000110
0b11000011 >> 20
0b00000000

한 자리를 오른쪽으로 이동하면 숫자를 2로 나누는 것과 같은 효과가 있습니다.

이 작업 중에 왼쪽에 추가된 상위 비트는 0이지만 항상 그런 것은 아닙니다 !

중요한!

부호 있는 숫자의 가장 왼쪽 비트를 부호 비트 라고 합니다 . 숫자가 양수이면 0; 그러나 숫자가 음수이면 이 비트는 1.

숫자의 비트를 오른쪽으로 이동하면 일반적으로 부호 비트 값도 이동하고 숫자의 부호가 손실됩니다. 따라서 음수의 경우(가장 왼쪽 비트가 1) 이 비트는 특별하게 취급됩니다. 숫자의 비트를 오른쪽으로 이동할 때 맨 왼쪽 0비트가 이면 왼쪽에 a가 추가되고 맨 왼쪽 비트가 이면 왼쪽에 0a가 추가됩니다 .11

그러나 위의 예에서는 결과가 아닌 것 같습니다. 왜? 정수 리터럴은 ints이고  실제로는 를 의미하기 때문입니다 . 즉, 맨 왼쪽 비트는 0입니다.0b111111110b00000000000000000000000011111111

많은 프로그래머가 이 오른쪽 시프트 동작에 불만을 품고 있으며 숫자가 항상 0으로 채워지는 것을 선호합니다. 그래서 Java는 또 다른 오른쪽 시프트 연산자를 추가했습니다 .

다음과 같이 작성되었습니다.

a >>> b

여기서 a 는 비트가 이동되는 숫자이고 는 해당 숫자의 비트를 오른쪽으로 b  이동하는 횟수입니다 . a이 연산자는 숫자 부호 비트의 원래 값에 관계없이 항상 왼쪽에 0을 추가합니다 a.



3. 플래그 작업

프로그래머는 비트 및 시프트 연산을 기반으로 거의 완전히 새로운 연구 분야인 플래그 작업을 만들었습니다.

컴퓨터에 메모리가 거의 없었을 때 많은 정보를 하나의 숫자에 집어넣는 것이 인기가 있었습니다. 숫자는 비트 배열로 취급되었습니다. int는 32비트이고 long은 64비트입니다.

true특히 논리( 또는 ) 값을 저장해야 하는 경우 이러한 숫자에 많은 정보를 쓸 수 있습니다 false. 싱글은 64개의 요소로 구성된 배열 long과 같습니다 boolean. 이러한 비트는 플래그 라고 하며 다음 작업을 사용하여 조작되었습니다.

  • 깃발을 꽂다
    (특정 비트를 와 동일하게 만들기 1)
  • 리셋 플래그
    (특정 비트를 와 동일하게 만들기 0)
  • 체크 플래그
    (특정 비트의 값을 확인)

비트 연산자로 수행하는 방법은 다음과 같습니다.

플래그 설정

특정 비트를 로 설정하려면 1비트를 설정하려는 숫자와 특수하게 생성된 숫자 사이에 비트 OR 연산을 수행해야 합니다. 여기서 해당 비트만 입니다 1.

예를 들어 숫자가 있고 0b000010105번째 비트를 로 설정해야 한다고 가정합니다 1. 이 경우 다음을 수행해야 합니다.

0b00001010 | 0b00010000 = 0b00011010

5번째 비트가 이미 1로 설정되어 있었다면 아무 것도 변경되지 않았을 것입니다.

일반적으로 플래그 설정 작업은 다음과 같이 작성할 수 있습니다.

a | (1 << b)

a 비트가 로 설정될 숫자는 어디에 있습니까 1? 그리고 b 설정할 비트의 위치입니다. 작업 중인 비트를 즉시 알 수 있기 때문에 여기서 왼쪽 시프트 연산자를 사용하는 것이 매우 편리합니다.

플래그 재설정

다른 비트를 방해하지 않고 특정 비트를 재설정(즉, 로 설정)하려면 재설정(즉, 으로 설정)하려는 비트의 숫자와 특수하게 생성된 숫자 사이에서 연산을 수행 0해야 합니다 . 여기서 모든 비트는 예외입니다 . 재설정하려는 비트에 대해.&01

예를 들어 숫자가 있고 0b000010104번째 비트를 로 설정해야 한다고 가정합니다 0. 이 경우 다음을 수행해야 합니다.

0b00001010 & 0b11110111 = 0b00000010

4번째 비트가 이미 0으로 설정되어 있었다면 아무 것도 변경되지 않았을 것입니다.

일반적으로 플래그 재설정 작업은 다음과 같이 작성할 수 있습니다.

a & ~(1 << b)

a 비트가 로 재설정될 숫자는 어디에 있습니까 0? 그리고 b 클리어할 비트의 위치입니다.

10이 되고자 하는 비트를 제외한 모든 비트가 있는 숫자를 얻으려면 먼저  왼쪽으로 1 bNOT 위치를 이동한 다음 비트 연산자를 사용하여 결과를 반전시킵니다.

플래그 확인

특정 플래그를 설정하거나 재설정하는 것 외에도 특정 플래그가 설정되어 있는지, 즉 특정 비트가 와 같은지 확인해야 하는 경우가 있습니다 1. 이것은 bitwise 를 사용하면 아주 쉽습니다 &.

1예를 들어 숫자에서 4번째 비트가 로 설정되어 있는지 확인해야 한다고 가정합니다 0b00001010. 그런 다음 다음을 수행해야 합니다.

if ( (0b00001010 & 0b00001000) == 0b00001000 )

일반적으로 플래그를 확인하는 작업은 다음과 같이 작성할 수 있습니다.

(a & (1 << b)) == (1 << b)

a 비트를 검사하는 번호는 어디에 있습니까? 그리고 b 검사할 비트의 위치입니다.


4. 암호화

비트 XOR연산은 간단한 암호화를 위해 프로그래머가 자주 사용합니다. 일반적으로 이러한 암호화는 다음과 같습니다.

result = number ^ password;

number 암호화하려는 데이터는 어디에 있으며 password 데이터의 "비밀번호"로 사용되는 특수 번호이며 result 암호화된 번호입니다.

number == (number ^ password) ^ password;

여기서 중요한 것은 XOR연산자가 숫자에 두 번 적용되면 "암호"와 상관없이 원래 숫자를 생성한다는 것입니다.

number 에서 복구하려면 encrypted result작업을 다시 수행하기만 하면 됩니다.

original number = result ^ password;

예:

class Solution
{
   public static int[] encrypt(int[] data, int password)
   {
     int[] result = new int[data.length];
     for (int i = 0; i <  data.length; i++)
       result[i] = data[i] ^ password;
     return result;
   }

   public static void main(String[] args)
   {
     int[] data =  {1, 3, 5, 7, 9, 11};
     int password = 199;

     // Encrypt the array of data
     int[] encrypted = encrypt(data, password);
     System.out.println(Arrays.toString(encrypted));

     // Decrypt the array of data
     int[] decrypted = encrypt(encrypted, password);
     System.out.println(Arrays.toString(decrypted));
   }
}