Java: использование побитовых операций
1. Побитовые (поразрядные) операции
В следующей таблице представлены побитовые операции применяемые в языке Java:
Побитовые операторы применяются к целочисленным типам long, int, short, byte, char. Побитовые операторы применяются к каждому отдельному биту каждого операнда.
A | B | A | B | A & B | A ^ B | ~A |
0 | 0 | 0 | 0 | 0 | 1 |
1 | 0 | 1 | 0 | 1 | 0 |
0 | 1 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 | 0 |
1.1. Побитовое ИЛИ (OR, |)
' 00101010 42
| 00001111 15
--------------
00101111 47
'
1.2. Побитовое И (AND, &)
' 00101010 42
& 00001111 15
--------------
00001010 10
'
1.3. Побитовое исключающее ИЛИ (XOR, ^)
' 00101010 42
^ 00001111 15
--------------
00100101 37
'
1.4. Побитовое НЕ (NOT, ~)
~ 00101010 42
-----------------
11010101
Рассмотрим теперь применение побитовых операций в программе. В следующем примере также показано применение метода Integer.toBinaryString()
, который приводит десятичное значение к двоичному:
public class BitwiseExample1 {
public static void main(String[] args) {
int a = 3;
int b = 6;
int c = a | b;
int d = a & b;
int e = a ^ b;
int f = ~b;
System.out.println("a = " + Integer.toBinaryString(a));
System.out.println("b = " + Integer.toBinaryString(b));
System.out.println("a | b = " + Integer.toBinaryString(c));
System.out.println("a & b = " + Integer.toBinaryString(d));
System.out.println("a ^ b = " + Integer.toBinaryString(e));
System.out.println("~ b = " + Integer.toBinaryString(f));
}
}
2. Битовые сдвиги в Java
Общая форма:
значение << количество
34<<3, 56>>2, 78>>>1
0001<<1 = 0010
0100>>1 = 0010
При сдвиге отрицательных чисел имеется разница в использовании операторов >> и >>>. Операция >> распространяет знаковый (левый) бит направо до конца, >>> заполняет нулями. У положительных чисел результат будет одинаков.
Типы byte
и short
продвигаются к типу int
при вычислении выражения.
Пример битовых сдвигов:
int i = 192;
i 00000000 00000000 00000000 11000000 (192)
i<<1 00000000 00000000 00000001 10000000 (384)
i>>1 00000000 00000000 00000000 01100000 (96)
i>>>1 00000000 00000000 00000000 01100000 (96)
int i = -192; (двоичная запись в доп. коде)
i 11111111 11111111 11111111 01000000 (-192)
i<<1 11111111 11111111 11111110 10000000 (-384)
i>>1 11111111 11111111 11111111 10100000 (-96)
i>>>1 01111111 11111111 11111111 10100000 (2147483552)
public class BitwiseExample2 {
public static void main(String[] args) {
byte a = 64; //0100 0000
byte b;
int i = a << 2; // 1 0000 0000
b = (byte) (a << 2); //0000 0000
System.out.println("a = " + a);
System.out.println("i = " + i);
System.out.println("b = " + b);
}
}
3. Побитовые операции с присваиванием
Также существуют побитовые операции с присваиванием:
4. Практическое применение побитовых операций
Побитовые операции имеют довольно широкое практическое применение, рассмотрим некоторые случаи:
4.1. Чётность числа
x & 1
- проверяет чётность числа. Если число четное - результат 0, нечетное - 1.
4.2. Деление числа на два
x<<1
– умножение на 2.x>>1
- деление на два с отбрасыванием любого остатка.
4.3. Шифрование числа
C = A ^ B
A = C ^ B
Представьте, что необходимо отправить в сообщении число 560 - пин-код от банковской карты. Если злоумышленник перехватит сообщение, то узнает пин-код и сможет воспользоваться им. Только отправитель и получатель могут знать пин-код. Чтобы этого не произошло, придумаем какое-то число - маску и сообщим его получателю заранее. Перед отправкой пин-кода, зашифруем его - применим побитовую операцию XOR: message^XOR
. И результат отправим. Если злоумышленник и перехватит сообщение, он не будет знать как его расшифровать. Адресат получает сообщение, расшифровывает пин-код с помощью имеющейся маски: message^maska
.
Следующий код иллюстрирует этот пример:
public class BitwiseExample3 {
public static void main(String[] args) {
int message = 560;
int maska = 67;
int codedMessage = message ^ maska;
int receivedMesssage = codedMessage ^ maska;
System.out.println("message = " + message);
System.out.println("message = " + Integer.toBinaryString(message));
System.out.println("codedMessage = " + codedMessage);
System.out.println("codedMessage = " + Integer.toBinaryString(codedMessage));
System.out.println("receivedMesssage = " + receivedMesssage);
System.out.println("receivedMesssage = " + Integer.toBinaryString(receivedMesssage));
}
}
4.4. Наложение маски
' 001010101
& 000100100
----------------
000000100
'
Презентацию с видео можно скачать на Patreon.
Зарегистрируйтесь или войдите, чтобы иметь возможность оставить комментарий.