1. 비트 왼쪽 시프트
Java에는 3개의 비트 시프트 연산자 도 있습니다 . 실제로 필요한 경우 숫자의 모든 비트를 여러 위치에서 왼쪽 또는 오른쪽으로 매우 간단하게 이동할 수 있습니다.
숫자의 비트를 왼쪽으로 이동하려면 비트 왼쪽 이동 연산자 가 필요합니다 . 다음과 같이 작성되었습니다.
a << b
여기서 a
는 비트가 이동되는 숫자이고, 는 해당 숫자의 비트를 왼쪽으로 b
몇 번 이동할 것인지를 나타내는 숫자입니다 . a
이 작업 중에 오른쪽에 추가된 하위 비트는 0입니다.
예:
예 | 결과 |
---|---|
|
|
|
|
|
|
|
|
한 자리를 왼쪽으로 이동하면 숫자에 2를 곱한 것과 같은 효과가 있습니다.
숫자에 16을 곱하고 싶습니까? 16은 24 와 같습니다 . 따라서 숫자 4자리를 왼쪽으로 이동합니다.
2. 비트 오른쪽으로 이동
비트를 오른쪽으로 이동할 수도 있습니다. 이렇게 하려면 비트 오른쪽 시프트 연산자 를 사용하십시오 . 다음과 같이 작성되었습니다.
a >> b
여기서 a
는 비트가 이동되는 숫자이고 는 해당 숫자의 비트를 오른쪽으로 b
이동하는 횟수입니다 .a
예:
예 | 결과 |
---|---|
|
|
|
|
|
|
|
|
한 자리를 오른쪽으로 이동하면 숫자를 2로 나누는 것과 같은 효과가 있습니다.
이 작업 중에 왼쪽에 추가된 상위 비트는 0이지만 항상 그런 것은 아닙니다 !
부호 있는 숫자의 가장 왼쪽 비트를 부호 비트 라고 합니다 . 숫자가 양수이면 0
; 그러나 숫자가 음수이면 이 비트는 1
.
숫자의 비트를 오른쪽으로 이동하면 일반적으로 부호 비트 값도 이동하고 숫자의 부호가 손실됩니다. 따라서 음수의 경우(가장 왼쪽 비트가 1
) 이 비트는 특별하게 취급됩니다. 숫자의 비트를 오른쪽으로 이동할 때 맨 왼쪽 0
비트가 이면 왼쪽에 a가 추가되고 맨 왼쪽 비트가 이면 왼쪽에 0
a가 추가됩니다 .1
1
그러나 위의 예에서는 결과가 아닌 것 같습니다. 왜? 정수 리터럴은 int
s이고 실제로는 를 의미하기 때문입니다 . 즉, 맨 왼쪽 비트는 0입니다.0b11111111
0b00000000000000000000000011111111
많은 프로그래머가 이 오른쪽 시프트 동작에 불만을 품고 있으며 숫자가 항상 0으로 채워지는 것을 선호합니다. 그래서 Java는 또 다른 오른쪽 시프트 연산자를 추가했습니다 .
다음과 같이 작성되었습니다.
a >>> b
여기서 a
는 비트가 이동되는 숫자이고 는 해당 숫자의 비트를 오른쪽으로 b
이동하는 횟수입니다 . a
이 연산자는 숫자 부호 비트의 원래 값에 관계없이 항상 왼쪽에 0을 추가합니다 a
.
3. 플래그 작업
프로그래머는 비트 및 시프트 연산을 기반으로 거의 완전히 새로운 연구 분야인 플래그 작업을 만들었습니다.
컴퓨터에 메모리가 거의 없었을 때 많은 정보를 하나의 숫자에 집어넣는 것이 인기가 있었습니다. 숫자는 비트 배열로 취급되었습니다. int는 32비트이고 long은 64비트입니다.
true
특히 논리( 또는 ) 값을 저장해야 하는 경우 이러한 숫자에 많은 정보를 쓸 수 있습니다 false
. 싱글은 64개의 요소로 구성된 배열 long
과 같습니다 boolean
. 이러한 비트는 플래그 라고 하며 다음 작업을 사용하여 조작되었습니다.
-
깃발을 꽂다(특정 비트를 와 동일하게 만들기
1
) -
리셋 플래그(특정 비트를 와 동일하게 만들기
0
) -
체크 플래그(특정 비트의 값을 확인)
비트 연산자로 수행하는 방법은 다음과 같습니다.
플래그 설정
특정 비트를 로 설정하려면 1
비트를 설정하려는 숫자와 특수하게 생성된 숫자 사이에 비트 OR 연산을 수행해야 합니다. 여기서 해당 비트만 입니다 1
.
예를 들어 숫자가 있고 0b00001010
5번째 비트를 로 설정해야 한다고 가정합니다 1
. 이 경우 다음을 수행해야 합니다.
0b00001010 | 0b00010000 = 0b00011010
5번째 비트가 이미 1로 설정되어 있었다면 아무 것도 변경되지 않았을 것입니다.
일반적으로 플래그 설정 작업은 다음과 같이 작성할 수 있습니다.
a | (1 << b)
a
비트가 로 설정될 숫자는 어디에 있습니까 1
? 그리고 b
설정할 비트의 위치입니다. 작업 중인 비트를 즉시 알 수 있기 때문에 여기서 왼쪽 시프트 연산자를 사용하는 것이 매우 편리합니다.
플래그 재설정
다른 비트를 방해하지 않고 특정 비트를 재설정(즉, 로 설정)하려면 재설정(즉, 으로 설정)하려는 비트의 숫자와 특수하게 생성된 숫자 사이에서 연산을 수행 0
해야 합니다 . 여기서 모든 비트는 예외입니다 . 재설정하려는 비트에 대해.&
0
1
예를 들어 숫자가 있고 0b00001010
4번째 비트를 로 설정해야 한다고 가정합니다 0
. 이 경우 다음을 수행해야 합니다.
0b00001010 & 0b11110111 = 0b00000010
4번째 비트가 이미 0으로 설정되어 있었다면 아무 것도 변경되지 않았을 것입니다.
일반적으로 플래그 재설정 작업은 다음과 같이 작성할 수 있습니다.
a & ~(1 << b)
a
비트가 로 재설정될 숫자는 어디에 있습니까 0
? 그리고 b
클리어할 비트의 위치입니다.
1
0이 되고자 하는 비트를 제외한 모든 비트가 있는 숫자를 얻으려면 먼저 왼쪽으로 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));
}
}
GO TO FULL VERSION