Бітові операції

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

Розрядні операції поділяються на:

  • логічні;
  • операції зміщенні чи зсуву;

Побітові оператори можна застосувати до всіх цілочисельних типів даних.

Логічні операції

Побітове заперечення або інверсія ~

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

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);

Дивіться також: