Битовые операции

Битовые операции – это операции которые выполняются над отдельно взятыми двоичными битами в числах. В битовых или поразрядных операциях, числа рассматриваются как последовательность нулей и единиц двоичной системы счисления.

Разрядные операции делятся на:

  • логические;
  • операции смещения;

Побитовые операторы можно применять ко всем целочисленным типам данных.

Логические операции

Побитовое отрицание или инверсия ~

“~” – унарный оператор, который инвертирует все биты аргумента. Все разряды с нулей переходят в единицы, а единицы в нули.

byte x = 0b00001111;
var y = (byte)~x; // 11110000

Побитовое сложение |

Логическое сложение(дизъюнкция) – бинарная операция выполняется над двоичными разрядами числа, если один из битов, которые суммируются, равен единице, то результатом будет единица, в противном случае ноль.

int a = 0b00011010;
int b = 0b00110001;
var c = a | b; //00111011

Побитовое умножение &

Логическое умножение(конъюнкция) – бинарная операция, во время которой перемножаются отдельно взятые биты числа.

int d = 0b00011010;
int e = 0b00110111;
var f = d & e; //00010010

Исключительная дизъюнкция ^

Логическое сложение по модулю (eXclusive OR) – бинарная операция, при которой результирующий бит принимает значение 1 только в случае, когда только один из слагаемых разрядов равен единице.

int g = 0b00010011;
int h = 0b00110101;
var k = g ^ h; //00100110

Операции смещения

Операции смещения – предназначены для смещения битового представления числа влево или вправо.

Оператор смещения влево <<

Бинарный оператор, который используется для смещения разрядов двоичного числа на N позиций влево, количество позиций передается в качестве второго операнда.

long num1 = 0b00001110;
long num2 = num1 << 3; 0b01110000;

Оператор смещения вправо >>

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

long num3 = 0b00001100;
long num4 = num3 >> 2; 0b00000011;

Использование поразрядных операций

Битовые флаги

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

Рассмотрим код программы для работы с битовыми флагами:

using System;

class Program
{
    private static int GetFlag(int data, int position)
    {
        //битовая маска
        var mask = 0b00000001;
        //смещение на позицию указанную как аргумент метода
        data = data >> position;
        //возвращаем значение флажка на заданной позиции
        return data & mask; 
    }

    private static int SetFlag(int data,  int bitValue, int position)
    {
        var mask = 0b00000001;
        //смещаем на указанное количество бит
        mask = mask << position; 

        if (bitValue == 1)
        {
            //выставляем в бит с индексом position значение 1
            return data | mask; 
        }
        else
        {
            //для сброса бита в ноль, сначала инвертируем маску
            return data & ~mask;
        }
    }

    static void Main(string[] args)
    {
        int flagSet = 0b10101010; //начальное значение
        flagSet = SetFlag(flagSet, 1, 4); //10111010
        flagSet = SetFlag(flagSet, 0, 5); //10011010
        Console.WriteLine(Convert.ToString(flagSet, 2));
        var flag = GetFlag(flagSet, 7);
        Console.WriteLine("Flag value : {0}", flag);
        Console.ReadLine();
    }
}     

Быстрое умножение и деление на степень двойки

С помощью операторов смещения, можно быстро находить результат умножения и деления на 2N(2, 4, 8, 16…).

using System;

class Program
{
    private static int MultTo2N(int num, int n)
    {
        return num << n;
    }

    private static int DivTo2N(int num, int n)
    {
        return num >> n;
    }

    static void Main(string[] args)
    {
        Console.WriteLine("5 * 16 = {0}", MultTo2N(5, 4)); // в метод передаем степень двойки (16 = 2 в 4-й)
        Console.WriteLine("64 / 8 = {0}", DivTo2N(64, 3)); // 8 = 2 в 3-й
        Console.ReadLine();
    }
}

XOR шифрование данных

На базе логического оператора XOR, можно реализовать простое шифрование данных:

int key = 0xACACAC; //ключ шифрования нужно выбирать большим за данные которые шифруются
int password = 123456789; //важные данные которые необходимо зашифровать

int encryptedPass = password ^ key;
Console.WriteLine("Зашифрованный пароль: {0}", encryptedPass);

int decryptedPass = encryptedPass ^ key;
Console.WriteLine("Расшифрованный пароль: {0}", decryptedPass);

Смотрите также: