простые операции над двоичным кодом в Java

Изначально размещено на странице https://www.wandercosta.com/java-bit-shift-and-bitwise-operators/

Битовый сдвиг и Побитовый - это операторы, которые делают двоичные вычисления совершенно простыми.

Несколько лет назад мне пришлось реорганизовать некоторую логику, используя операции битового сдвига. Это заставило меня подумать, что большая часть разработчиков никогда не видели и даже не понимали, что такое битовый сдвиг и побитовые операции.

Эти операторы предоставляют отличное решение, которое необходимо знать для конкретных проблем, таких как сетевые вычисления (IP и маска сети); обработка привилегий на основе битовых полей; связь, включающая контрольные суммы, четность, управление потоком (например: последовательная связь); сжатие; шифрование и др.

Еще один важный момент - производительность. Вместо реализации более сложных алгоритмов можно выполнить двоичную обработку с минимальными усилиями, поскольку поразрядный и битовый сдвиг являются примитивными операциями, напрямую поддерживаемыми процессорами .

Операторы:

  • ~, который выполняет поразрядное дополнение;
  • &, который выполняет побитовое И;
  • ^, который выполняет побитовое исключающее ИЛИ;
  • |, который выполняет поразрядное включающее ИЛИ;
  • <<, который сдвигает битовый шаблон влево;
  • >>, который сдвигает битовый шаблон вправо;
  • >>>, который сдвигает ноль в крайнее левое положение.

Два дополнения

Чтобы понять, что такое двоичные операции, необходимо понимать, как целые числа со знаком представлены в двоичной системе счисления. Мой предыдущий пост Дополнение двух описывает это.

~ Побитовое дополнение

Побитовое дополнение ~ - это оператор двоичного инвертирования битовой комбинации значения.

Пусть A будет int со значением 18:

  • 0000 0000 0000 0000 0000 0000 0001 0010 представляет собой A, который равен 18;
  • 1111 1111 1111 1111 1111 1111 1110 1101 представляет ~ A, что равно -19 в Дополнении до двух.

Все биты были инвертированы, таким образом, 0 превратилось в 1 и 1 на 0. Из-за архитектуры Два дополнения каждый ~ X будет −X − 1 − X − 1.

& Побитовое И

Побитовое И & - это оператор для выполнения двоичного соединения.

Пусть A будет short со значением 18, а B будет short со значением 4216;

  • 0000 0000 0001 0010 представляет собой A, который равен 18;
  • 0001 0000 0111 1000 представляет собой B, который равен 4216;
  • 0000 0000 0001 0000 представляет собой A и B, то есть 16.

Двоичное соединение превращает два 1 в 1, а все остальное в 0. В приведенном выше примере единственным совпадающим битом в A и B был 5-й бит (справа налево), в результате чего значение результата было 16.

^ Побитовое исключающее ИЛИ

Побитовое исключающее ИЛИ ^ - это оператор для выполнения двоичных исключающих дизъюнкций, также известный как XOR.

Используя тот же предыдущий пример, пусть A будет short со значением 18, а B будет short со значением 4216;

  • 0000 0000 0001 0010 представляет собой A, который равен 18;
  • 0001 0000 0111 1000 представляет B, который равен 4216;
  • 0001 0000 0110 1010 представляет собой A ^ B, то есть 4202.

Двоичная исключительная дизъюнкция превращает одно и только одно, 1 в 1, а все остальное - в 0. В приведенном выше примере результатом было 4202.

| Побитовое инклюзивное ИЛИ

Побитовое инклюзивное ИЛИ | - это оператор для выполнения двоичных включающих дизъюнкций, также известный как просто ИЛИ.

Используя тот же предыдущий пример, пусть A будет short со значением 18, а B будет short со значением 4216;

  • 0000 0000 0001 0010 представляет собой A, который равен 18;
  • 0001 0000 0111 1000 представляет В, который равен 4216;
  • 0001 0000 0111 1010 представляет собой A ^ B, то есть 4218.

Двоичная инклюзивная дизъюнкция превращает два 0 в 0 и все остальное в 1. В приведенном выше примере результатом было 4218.

<< Подпись влево Shift

Левый сдвиг со знаком << - это оператор сдвига битов влево.

Пусть A будет short со значением 25.

  • 0000 0000 0001 1001 представляет собой A, равный 25;
  • 0000 0000 0110 0100 представляет собой A «2, равное 100.

Вышеупомянутая операция сдвинула на 2 позиции влево, в результате чего значение результата было 100.

Важно понимать, что происходит в самом старшем разряде. Чтобы понять это, возьмем другой пример.

Пусть B будет short со значением 8192.

  • 0010 0000 0000 0000 представляет В, который равен 8192;
  • 0100 0000 0000 0000 представляет собой B «1, что составляет 16384;
  • 1000 0000 0000 0000 представляет собой B 2, что равно -32768 в« дополнении до двух .
  • 0000 0000 0000 0000 представляет собой B «3, что равно 0.

То есть простые сдвиги. Во время сдвига влево особого поведения не происходит.

>> Подпись, сдвиг вправо

Signed Right Shift >> - это оператор сдвига битов вправо с сохранением сигнала.

Пусть A будет short со значением 25.

  • 0000 0000 0001 1001 представляет собой A, равный 25;
  • 0000 0000 0000 0110 представляет собой A »2, что равно 12.

Вышеупомянутая операция сдвинула биты на 2 позиции вправо, в результате чего значение результата составило 12.

Чтобы выяснить, что происходит в самом старшем разряде, давайте также рассмотрим другие примеры.

Пусть B будет short со значением 16384.

  • 0100 0000 0000 0000 представляет собой B, который равен 16384;
  • 0010 0000 0000 0000 представляет собой B »1, что равно 8192.

Пусть C будет short со значением -32768.

  • 1000 0000 0000 0000 представляет собой C, который равен -32768;
  • 1100 0000 0000 0000 представляет собой B »1, что равно -16384;
  • 1110 0000 0000 0000 представляет собой B »1, что равно -8192;

Таким образом, мы заключаем, что Signed Right Shift сохраняет сигнал. Другими словами, он немного сдвигается в крайнем левом положении на то же значение, что и сигнал.

>>> Беззнаковый сдвиг вправо

Беззнаковый сдвиг вправо >>> - это оператор сдвига битов вправо без учета сигнала.

Поведение такое же, как и при сдвиге вправо со знаком, за исключением: бит, добавленный слева, ВСЕГДА равен нулю. Возьмем последний пример подписанного сдвига вправо:

Пусть C будет short со значением -32768.

  • 1000 0000 0000 0000 представляет собой C, который равен -32768;
  • 0100 0000 0000 0000 представляет собой B »1, что составляет 16384;
  • 0010 0000 0000 0000 представляет собой B »1, что равно 8192;

В результате всегда получается положительное значение, которое является квадратным корнем из абсолютного значения C.

Особенности смены

Сдвиги в двоичных представлениях - это ярлыки для вычисления степеней двойки и квадратных корней, ТОЛЬКО ЕСЛИ они не изменяют самый старший бит.

При сдвиге A влево на одну позицию, если самый старший бит не изменяется, результатом будет Aˆ2. При сдвиге A вправо на одну позицию, если самый старший бит не изменяется, результатом будет √A.