Phép toán thao tác bit trong C++ (Bitwise operation)

2
8783
84/ 100

Trong bài viết này, chúng ta sẽ tìm hiểu về các phép toán thao tác bit (bitwise operation). Trong đơn vị logic số học (nằm trong CPU), các phép toán như: cộng, trừ, nhân và chia được thực hiện ở cấp độ bit. Để thực hiện các phép toán cấp độ bit trong C++, các toán tử bitwise được sử dụng.

Phép toán thao tác bit trong C++ (Bitwise operation)
Một bức hình biểu diễn bởi các con số 0 và 1 trích từ bộ phim nổi tiếng Ma trận (The Matrix)

Trước khi đi vào các bài tập ví dụ, chúng ta hãy ôn lại một chút kiến thức về các phép toán logic, bao gồm 6 phép toán cơ bản:

&AND
|OR
^XOR
~NOT
<<Dịch bit sang trái
>>Dịch bit sang phải

Các phép toán thao tác bit cơ bản

Phép toán AND (&)

Kết quả của phép AND sẽ là 1 nếu cả 2 toán hạng là 1. Nếu một trong hai toán hạng là 0 thì kết quả sẽ là 0, sau đây là bảng chân trị của phép AND:

ABA & B
000
100
010
111

Ví dụ phép AND giữa 2 số thập phân là 5 và 3:

Minh họa với C++:

Kết quả:

Phép toán OR (|)

Kết quá của phép OR sẽ là 1 nếu một trong hai toán hạng là 1. Trong C++, phép OR được ký hiệu là |. Bảng chân trị của phép OR

ABA | B
000
101
011
111

Ví dụ phép OR của 12 và 25

Minh họa với C++:

Kết quả:

Phép toán XOR  (^)

Kết quả của phép XOR là 1 nếu 2 toán hạng có giá trị khác nhau.

ABA ^ B
000
101
011
110

Minh họa với C++:

Kết quả:

Ngoài ra, có 2 tính chất đặc biệt với phép XOR:
  • A ^ A = 0 (1 toán hạng XOR với chính nó sẽ bằng 0)
  • A ^ 0 = A (Bất kỳ toán hạng nào XOR với 0 đều bằng chính nó)

Phép toán NOT (~)

Toán tử NOT là toán tử 1 ngôi. Nó thay đổi toán hạng từ 0 sang 1 và ngược lại

A~A
01
10

Minh họa với C++:

Kết quả:

Chúng ta thấy kết quả của ~30 là -31 thay vì 225, tại sao lại như vậy?

Để hiểu được điều này chúng ta sẽ nói qua một chút về bù 2 (2s complement):

Bù 2 của một số sẽ bằng bù 1 (~) của số đó cộng thêm 1

Đối với bất kỳ số nguyên n, thì ~n sẽ bằng -(n+1). Vì ~n được biểu diễn dưới dạng bù 2 và bù 2 của ~n sẽ là -(~(~n)+1)=-(n+1)

Suy ra kết quả ở đầy sẽ là -31 thay vì 225 vì bù 1 của 30 (~30) là 225, bù 2 của 225 là -31.

Toán tử dịch bit

Dịch phải (>>)

Toán tử dịch phải bit sẽ dịch tất cả các bit sang phải bởi một số nhất định

Dịch trái bit (<<)

Toán tử dịch trái bit sẽ dịch tất cả các bit sang trái bởi một số nhất định

Minh họa với C++:

Kết quả:

Bài tập phép toán thao tác bit

Bạn có thể thực hành các bài tập liên quan tới phép toán thao tác bit (bitwise) trên nền tảng Luyện Code tại đây. Sau đây sẽ là 2 bài toán kinh điển có sự hỗ trợ của phép toán thao tác bit đi kèm hướng dẫn và lời giải tham khảo sử dụng C++.

Kiểm tra tính chẵn lẻ của một số

Đề bài: Cho 1 số nguyên n, kiểm tra xem n là chẵn hay lẻ?

Chúng ta sẽ thấy 1 điều rằng những số chẵn ở dạng nhị phân thì bit ngoài cùng bên phải sẽ luôn là bit 0, đối với số lẻ thì bit ngoài cùng bên phải sẽ luôn là 1. Dựa vào điều này ta có thể dễ dàng biết được tính chẵn lẻ bằng cách lấy số đó AND(&) với 1 nếu kết quả bằng 1 thì đó là số lẻ, ngược lại nếu bằng 0 sẽ là số chẵn. Ví dụ:

Lời giải tham khảo với C++:

Tìm số xuất hiện 1 lần duy nhất trong mảng

Đề bài: Cho 1 mảng các số nguyên, mỗi số trong mảng xuất hiện 2 lần, ngoại trừ 1 số xuất hiện đúng 1 lần, hãy tìm số xuất hiện đúng 1 lần đó?

Đối với bài toán này chúng ta sẽ có khá nhiều cách giải, có thể sử dụng hash table, độ phức tạp thời gian sẽ là O(n) nhưng lại yêu cầu nhiều bộ nhớ hơn. Vậy ở đây chúng ta sẽ sử dụng các phép toán bit với độ phức tạp thời gian là O(n) và không gian là O(1).

Như mình đã đề cập ở phần XOR(^), phép XOR có 2 tính chất đặc biệt, và ý tưởng cho bài toán này là chúng ta chỉ cần XOR hết tất cả các phần tử trong mảng lại với nhau, 2 phần tử trùng nhau sẽ trả về về 0 và còn lại phần tử xuất hiện đúng 1 lần sẽ XOR với 0 và trả về phần tử đó.

Lời giải tham khảo với C++:

Kết quả:

Trên đây là nội dung bài viết về các phép toán thao tác bit đi kèm các ví dụ sử dụng ngôn ngữ C++. Nếu bạn đọc có nhận xét hoặc thắc mắc có thể để lại bình luận phía cuối bài viết hoặc đặt câu hỏi tại nhóm Lập Trình Không Khó.

Subscribe
Notify of
guest
2 Bình luận
Inline Feedbacks
View all comments