Бітові операції – це операції які виконуються над окремими двійковими бітами в числах. В бітових або порозрядних операціях, числа розглядаються як послідовності нулів та одиниць двійкової системи числення.
Розрядні операції поділяються на:
- логічні;
- операції зміщенні чи зсуву;
Побітові оператори можна застосувати до всіх цілочисельних типів даних.
Логічні операції
Побітове заперечення або інверсія ~
“~” – унарний оператор, який інвертує всі біти вхідного аргументу – всі біти з нулів переходять у одиниці, а одиниці в нулі.
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);