Поразрядные операции с числами Python
Добавить в избранноеПри работе с числами в программировании мы часто сталкиваемся с различными операциями, которые могут быть выполнены над отдельными битами чисел. Эти операции, известные как поразрядные операции, играют важную роль в различных аспектах программирования, начиная от простого шифрования до более сложных математических операций. Давайте взглянем на некоторые из них.
Двоичное представление чисел
В двоичной системе каждое число представлено разрядами, которые могут быть либо 0, либо 1. Например, число 5 в двоичной системе будет представлено как 101. Для вывода числа в двоичной системе в Python используется спецификатор 0b. Также можно определять числа прямо в двоичной форме с помощью префикса 0b. Это основа для понимания поразрядных операций.
Пример:
number = 5 print(f"number = {number:0b}") # number = 101
Без указания спецификатора функция print() выводит число в десятичной системе.
При этом Python позволяет сразу определять число в двоичной форме. Для этого число в двоичной форме указывается после префикса 0b:
number = 0b101 # определяем число в двоичной форме print(f"number = {number:0b}") # number = 101 print(f"number = {number}") # number = 5 - в десятичной системе
Логические операции
Логические операции выполняются над отдельными разрядами числа. В Python есть следующие логические операции:
&(логическое умножение)
Умножение производится поразрядно, и если у обоих операндов значения разрядов равно 1, то операция возвращает 1, иначе возвращается число 0. Например:
x1 = 2 # 010 y1 = 5 # 101 z1 = x1 & y1 print(f"z1 = {z1}") # z1 = 0 x2 = 4 # 100 y2 = 5 # 101 z2 = x2 & y2 print(f"z2 = {z2}") # z2 = 4 print(f"z2 = {z2:0b}") # z2 = 100
В первом случае у нас два числа 2 и 5. 2 в двоичном виде представляет число 010, а 5 - 101. Поразрядно умножим числа (0*1, 1*0, 0*1) и в итоге получим 000.
Во втором случае у нас вместо двойки число 4, у которого в первом разряде 1, так же как и у числа 5, поэтому в итоге получим (1*1, 0*0, 0 *1) = 100, то есть число 4 в десятичном формате.
| (логическое сложение)
Похоже на логическое умножение, операция также производится по двоичным разрядам, но теперь возвращается единица, если хотя бы у одного числа в данном разряде имеется единица. Например:
x1 = 2 # 010 y1 = 5 # 101 z1 = x1|y1 # 111 print(f"z1 = {z1}") # z1 = 7 print(f"z1 = {z1:0b}") # z1 = 111 x2 = 4 # 100 y2 = 5 # 101 z2 = x2 | y2 # 101 print(f"z2 = {z2}") # z2 = 5 print(f"z2 = {z2:0b}") # z2 = 101
^ (логическое исключающее ИЛИ)
Если значения текущего разряда у обоих чисел разные, то возвращается 1, иначе возвращается 0. Также эту операцию называют XOR. Например:
x = 9 # 1001 y = 5 # 0101 z = x ^ y # 1100 print(f"z = {z}") # z = 12 print(f"z = {z:0b}") # z = 1100
Здесь число 9 в двоичной форме равно 1001. Число 5 равно 0101. Операция XOR дает следующий результат: 1^0, 0^1, 0^0, 1^1. Здесь мы видим, что первые два разряда чисел содержат разные значения, поэтому первые два разряда получат значение 1. А последние два разряда чисел содержат одинаковые значения, поэтому последние два разряда получат значение 0. Таким образом, мы получаем число 1100 или 12 в десятичной системе.
нередко данную операцию применяют для простого шифрования:
x = 45 # Значение, которое надо зашифровать - в двоичной форме 101101 key = 102 # Пусть это будет ключ - в двоичной форме 1100110 encrypt = x ^ key # Результатом будет число 1001011 или 75 print(f"Зашифрованное число: {encrypt}") decrypt = encrypt ^ key # Результатом будет исходное число 45 print(f"Расшифрованное число: {decrypt}")
"~" инверсия
Инвертирует число. Выражение ~x фактически аналогично - (x+1). Например:
x = 5 y = ~x print(f"y: {y}") # -6
В Python операция инверсии числа (~x) инвертирует каждый бит числа x. Для лучшего понимания, представьте, что числа в компьютере представлены в двоичной системе, то есть как последовательности нулей и единиц.
Давайте рассмотрим пример с числом 5. В двоичном виде оно записывается как 0000 0101. Используя операцию инверсии (~), каждый бит этого числа инвертируется: каждый ноль становится единицей, и каждая единица - нулем. Таким образом, после инверсии получается число 1111 1010.
Теперь возникает вопрос: почему результат -6?
В Python и многих других языках программирования числа представляются в двоичном дополнительном коде. В этой системе отрицательные числа представлены с использованием дополнительного кода. Дополнительный код отрицательного числа получается путем инвертирования битов этого числа и последующим прибавлением 1.
После инверсии битов числа 5 мы получаем 1111 1010. Теперь, чтобы получить дополнительный код этого числа, добавим к нему 1:
1111 1010 # Результат инверсии битов числа 5
+ 1
------------
1111 1011 # Результат
Таким образом, получившийся результат 1111 1011 в двоичном дополнительном коде представляет собой -6 в десятичном представлении.
Таким образом, операция инверсии (~x) в Python фактически аналогична выражению -(x+1).
Операции сдвига
Операции сдвига также производятся над разрядами чисел. Сдвиг может происходить вправо и влево.
x<
Таким образом, если исходное число, которое надо сдвинуть в ту или другую строну, делится на два, то фактически получается умножение или деление на два. Поэтому подобную операцию можно использовать вместо непосредственного умножения или деления на два. Например:
a = 16 # в двоичной форме 10000 b = 2 c = a << b # Сдвиг числа 10000 влево на 2 разряда, равно 1000000 или 64 в десятичной системе print(c) #64 d = a >> b #Сдвиг числа 10000 вправо на 2 разряда, равно 100 или 4 в десятичной системе print(d) #4
При этом числа, которые участвую в операциях, необязательно должны быть кратны 2::
a = 22 # в двоичной форме 10110 b = 2 c = a << b # Сдвиг числа 10110 влево на 2 разряда, равно 1011000 или 88 в десятичной системе print(c) # 88 d = a >> b # Сдвиг числа 10110 вправо на 2 разряда, равно 101 или 5 в десятичной системе print(d) # 5
Понимание поразрядных операций с числами является важным аспектом в программировании. Эти операции могут быть использованы для решения различных задач, начиная от простых операций с битами до сложных математических алгоритмов.