Побитовый оператор

Побитовый оператор — оператор для манипуляций с отдельными битами целого числа. То же: bitwise operator.

Вся современная цифровая электроника, как известно, основана на двоичной системе, где самая маленькая ячейка памяти может иметь значение 0 или 1 (нет сигнала или есть сигнал). Вся другая информация образуется сочетанием таких единичных сигналов. Десятеричное число 140, например, образуется следующим сочетанием нулей и единиц:

1> 2#10001100.
140

Первый бит отвечает за 128, второй — за 64, третий — за 32, четвёртый — за 16, пятый — за 8, шестой — за 4, седьмой — за 2, восьмой — за 1. Поэтому и получается, что 140 = 128 + 8 + 4.

Любое изменение информации сопровождается изменениями в битах (например, использование оператора сложения). Вот так число 140 поменяется, если к нему добавить 1:

1> io:format("~.2# ~n", [140+1]).
2#10001101

Но иногда хочется более явно воздействовать на биты числа. Для этого и существуют побитовые операторы.

band — побитовое И

В обоих числах сравниваются биты: первые биты, вторые биты и т.д. Если оба биты равны 1, значит, в итоговом числе на этой позиции тоже будет 1. В противном случае будет 0.

1> X = 2#11010101.
213
2> Y = 2#11001100.
204
3> io:format("~.2# ~n", [X band Y]).
2#11000100 
ok
4> io:format("~.10# ~n", [X band Y]).
10#196 
ok

Вот так из чисел 213 и 204 мы получили 196. Если угодно, мы можем это проверить:

5> 213 band 204 == 196. 
true

bor — побитовое ИЛИ

Биты сравниваются аналогично. Но сейчас если оба биты равны 0, значит, в итоговом числе на этой позиции тоже будет 0. В противном случае будет 1. Иными словами, если хотя бы в одной ячейке будет 1, значит в итоговой тоже будет 1.

11110000
bor
10101010
—-------
11111010 

bxor — побитовое исключающее ИЛИ

Если биты одинаковые, в итоге будут нули. Если разные — единицы.

11110000
bxor
10101010
—-------
01011010 

bnot — побитовое отрицание

Это унарный оператор. Каждый бит меняет значение на противоположный: 0 на 1, 1 на 0.

1> io:format("~p ~n", [bnot 2#10001100]).
-141

bsl — битовый сдвиг влево

Первый операнд — число, над которым проводим манипуляции. Второй операнд — количество битов, на которое сдвигаем первое число.

1> io:format("~.2# ~n", [2#10001100 bsl 1]).
2#100011000 
ok
2> io:format("~.10# ~n", [2#10001100 bsl 1]).
10#280 
ok

Вот так мы сдвинули биты на 1 позицию влево, и число 140 превратилось в 280. Раз каждый бит сместился на более старшую позицию (в 2 раза), значит, и всё число увеличилось тоже в 2 раза. Если сместим на 3 позиции, то итоговое число будет в 8 раз больше.

3> io:format("~.2# ~n", [2#10001100 bsl 3]).
2#10001100000 
ok
4> io:format("~.10# ~n", [2#10001100 bsl 3]).
10#1120 
ok

Если в исходном числе был байт (восемь бит), то стало 11, потому что мы добавили 3 бита. Все добавляемые биты — нули.

Правый операнд может быть отрицательным числом, и тогда bsl работает как bsr, то есть биты сдвигаются вправо.

5> io:format("~.2# ~n", [2#10001100 bsl -3]).
2#10001 
ok

bsr — битовый сдвиг вправо

Работает как bsl, только сдвигает вправо.


© Алексей Карманов, 2024.