Sơ lược

Phép thao tác trên bit Kí hiệu Mô tả
AND & Cả hai bit là 1, trả về 1. Ngược lại trả về 0.
OR \ Một trong hai bit là 1, trả về 1. Ngược lại trả về 0.
XOR ^ Hai bit khác nhau trả về 1. Ngược lại trả về 0.
NOT ~ Đảo bit, 0 thành 1, 1 thành 0.
Dịch trái - Shift left << Dịch tất cả các bit sang trái.
Dịch phải - Right left >> Dịch tất cả các bit sang phải.

Ứng dụng

Số nguyên

Thay đổi bit

// Đưa bit thứ n thành 1
x |= (1 << n);

//Đưa bit 0 ngoài cùng thành 1
x |= (x+1);

//Đưa bit thứ n về 0
x &= ~(1 << n);

//Đưa bit 1 ngoài cùng về 0
x &= (x-1);

//Đảo bit thứ n
x ^= (1 << n);

//Lấy ra bit thứ n
(x >> n) & 1;

//Hoán đổi 2 bit cạnh nhau
((x & 10101010) >> 1) | ((x & 01010101) << 1);

Nhân / Chia x với $2^n$

x << n //nhân
x >> n //chia

Làm tròn lên lũy thừa cơ số 2

x--;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
x++;

Làm tròn xuống lũy thừa cơ số 2

x--;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
x++;
x = x >> 1; //vẫn là đoạn code trên nhưng thêm dòng này

Lấy phần nguyên của x

x >> 0;
6.723 >> 0; //6   

Đảo dấu x

x = ~x + 1; // hoặc
x = (x ^ -1) + 1; // x = -x

Giá trị tuyệt đối của x

int abs = (x ^ (x >> 31)) - (x >> 31);

Ước lũy thừa cơ số 2 lớn nhất của x

x & (-x);

Giá trị nguyên nhỏ nhất / lớn nhất

int minInt = 1 << 31;
int minInt = 1 << -1;

int maxInt = ~(1 << 31);
int maxInt = (1 << 31) - 1;
int maxInt = (1 << -1) - 1;
int maxInt = -1u >> 1;

int maxLong = ((long)1 << 127) -1;

Số nhỏ nhất / lớn nhất giữa 2 số

//Cách 1
int min = a & ((a-b) >> 31) | b & (~(a-b) >> 31);
int max = b & ((a-b) >> 31) | a & (~(a-b) >> 31);

//Cách 2
int min = (b ^ (a ^ b) & -(a < b));
int max = (a ^ (a ^ b) & -(a < b));

Trung bình cộng 2 số

int avg = (x + y) >> 1;
int avg = ((x ^ y) >> 1) + (x & y);

Hoán đổi giá trị 2 biến

//Cách 1
a ^= b;
b ^= a;
a ^= b;

//Cách 2
a = a ^ b ^ (b = a)

Gõ nhanh điều kiện if

Trong một số trường hợp, ta sẽ có đoạn code tựa tựa vầy:

if(x == a)
    x = b;
//hoặc
if(x == b)
    x = a;

Tương tự, ta đưa đoạn code về dòng sau với phép XOR:

x ^= a ^ b;

Kiểm tra

  • giá trị của bit thứ n

x & (1 << n)
  • x là số lẻ

(x & 1) == 1;
  • x là lũy thừa cơ số 2

x > 0 && (x & (x - 1)) == 0;
  • a = b

(Nhanh hơn 35% trong Javascript)

(a ^ b) == 0;
  • 2 số a, b cùng dấu

(a ^ b) >= 0;

Chuỗi

Chuyển kí tự thường thành hoa

c & '_'

Nếu kí tự được chuyển đã là kí tự hoa thì không thay đổi. Ví dụ:

char c;
c = 'a' & '_';  //c = 'A'
c = 'A' & '_';  //c = 'A'

Chuyển kí tự hoa thành thường

c | ' '

Nếu kí tự được chuyển đã là kí tự thường thì không thay đổi. Ví dụ:

char c;
c = 'A' | ' ';  //c = 'a'
c = 'a' | ' ';  //c = 'a'

Đảo ngược kiểu kí tự

c ^ ' '

Ví dụ:

char c;
c = 'A' ^ ' '; //c = 'a'
c = 'a' ^ ' '; //c = 'A'

Vị trí của kí tự trong bảng chữ cái

//Đối với chữ thường
c ^ '`'

//Đối với chữ hoa
c ^ '@'

//Không phân biệt
c & "\x1F"

Nhảm nhí khác

Dùng XOR để mã hóa một chuỗi

#include<iostream>
#define key 5

int main(){
    std::string s;
    std::cin >> s;
    
    //Mã hóa
    for(char &i : s){
        i ^= key;
    }
    std::cout << s + "\n";
    
    //Giải mã
    for(char &i : s){
        i ^= key;
    }
    std::cout << s + "\n";
}
Input:  Hello
Output: M`iij
        Hello

Đổi hệ màu từ R5G5B5 sang R8G8B8

R8 = (R5 << 3) | (R5 >> 2)
G8 = (R5 << 3) | (R5 >> 2)
B8 = (R5 << 3) | (R5 >> 2)

Viết xong cái này thì mình cũng sắp lú rồi, cảm ơn vì đã đọc.