heap.tech
лаборатория велосипедов
×

Bitwise. Побитовые операторы и основы программирования.

14 января 2016
Я занимаюсь разработкой, поэтому среди моих знакомых есть некоторая часть людей, которые занимаются тем же, ну или как-то связаны с этой областью. У всех них разные задачи, цели и средства достижения этих целей. Но всеже есть одна вещь, которая всех их объединяет – большинство из них напрочь забыли об основах программирования. По большому счету это закономерно - почти все используют высокоуровневые языки, исполняемые в песочнице фреймворка, поэтому программа третьего курса университета забывается. За ненадобностью. На совсем. Безвозвратно.

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

В качестве языка для примеров я буду использовать C#, хотя в нем нет возможности записать число в двоичном представлении.
Максимальное значение переменной с типом uint может быть равно 4294967295 или 2 в 32 степени. Стоит помнить, что 0 тоже считается, поэтому в конце 5, а не 6.
Следовательно, максимальное значение переменной int равно 2147483647 или в степени 31. Последний 32 байт указывает на знак, то есть 2147483647 или -2147483647.

Тоже самое касается типов long и short, но у них другая разрядность (64 и 16 соответственно).
Немного по-другому в c# обстоят дела с типом byte. Тип byte имеет 8 разрядов (8 бит) без указания знака. То есть значение переменной с типом byte всегда положительное.

Итак

byte b = 255; //2 ^ 8 без знака

int i = 2147483647; //2 ^ 31 +/-

uint uI = 4294967295; //2 ^ 32 без знака

long l = 9223372036854775807; //2 ^ 63 +/-

ulong uL = 18446744073709551616; //2 ^ 64 без знака


Теперь можно перейти к системам счисления. Например двоичной. Значение переменной int равное единице будет представлено так
00000000000000000000000000001

Или число 255, максимально возможное значение byte (8 бит)
000000000000000000000011111111

Именно с числом 255 далее я буду свои эксперименты. Число 255 в двоичной системе можно записать так 11111111, подразумевается, что старшие биты равны 0. Еще можно записать так 0b11111111 или так 0b00000000000000000000000011111111 но, в c# это невозможно.

На этом вводная часть закончена. Время перейти к практике и битовым операторам.

Первый битовый оператор это “&” или побитовое И. Оператор & отличается от логического, не смотря на одинаковую частную запись.
Описать действия битового оператора & можно так: оператор & сравнивает двоичное представление двух чисел, результат сравнения равен единице только когда оба биты двух чисел тоже равны единицам.

Пример
000000000000000000000011111111 & 00000000000000000000000000001

Получиться
00000000000000000000000000001 //или единица


Битовый оператор “|” или побитовое ИЛИ. Или черточка. Опятьже не путать с логическим оператором.
Оператор | (черточка) действует так: в результате сравнения двух бит будет единица, если хотябы один из них равен единице.

Пример
000000000000000000000011111111 | 00000000000000000000000000001

Получиться
000000000000000000000011111111 //(без изменений, тоже число 255)


Оператор “~” известен как побитовое НЕ. Оператор ~ просто заменяет все биты в числе A на противоположные.

Например
~000000000000000000000011111111


Получиться
111111111111111111111100000000 //или -256

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

Операторы смещения битов “<<” и “>>”. Операторы >> и << сдвигают разряды числа A вправо или влево на указанное количество битов B.

Например
000000000000000000000011111111 >> 1


Получиться
000000000000000000000001111111 //или 127


И левый сдвиг
000000000000000000000011111111 << 1


Получиться
000000000000000000000111111110 //или 510


510 получается потому, что при любом сдвиге появляющийся новый бит всегда равен 0. Поэтому, чтобы получить 512 нужно осуществить арифметическое сложение, то есть добавить единичку: 0b111111110 + 1

И наконец оператор “^”, исключающее ИЛИ. Еще его называют XOR.
Оператор XOR один из моих любимых – у него есть очевидные отличия, что расширяет сферу его применения. Но об этом я расскажу в следующей статье.

XOR возвращает единицу, только если один бит в числе A или в B равен единице. Если оба бита в этих числах единицы - результатом будет 0. Если вы будете сравнивать два числа оператором XOR и к полученному результату опять примените XOR – вы получите исходное число (конечно же вы будете использовать одно из чисел, которое было использовано ранее).

Например
000000000000000000000011111111 ^ 000000000000000000000000000001


Получиться
000000000000000000000011111110


Возьмем получившееся число и опять применим ^ с той же единичкой 000000000000000000000000000001.

Получиться
000000000000000000000011111111


Другими словами
X ^ Y = Z; Z ^ Y = X; /* OR */ X ^ Y ^ Y = X;


Результат выполнения оператора XOR обратим, если вы используете операнд из первоначального условия. Операторы & и | не обратимы.

В случае с оператором & единица будет только тогда, когда оба бита единицы. Иначе результат будет 0, вне зависимости от того, в каком бите какого числа стоит единица.

В случае с оператором | - единица будет только тогда, когда один бит равен единице. В результате всегда будет 1, вне зависимости от того, в каком бите какого числа стоит единица.

В следующей статье я расскажу о практиках применения битовых операторов.
 
1515
0

Оставлять комментарии могут только зарегистрированные пользователи

пока никто не оставлял комментариев