Caác hàm xử lý bit trong c++

Đề tài này sẽ cung cấp cho các bạn những kiến thức về việc sử dụng các phép toán logic từ đó giúp cho việc thiết kế các biểu thức logic dùng rất nhiêu trong các phép toán điều kiện được nhanh chóng, chính xác, hiệu quả.

* Quy ươc về vị trí của các bit;
Mỗi byte bao gồm 8 bit được mã số từ phải sang trái còn gọi là bit thấp đến bit cao. Bit nằm ở bên phải được xem là thấp hơn bit nằm ở bên trái. Các bit được đánh số như sau:
7 6 5 4 3 2 1 0


Mỗi bit có thể nhận 1 trong 2 giá trị là 0 hoặc 1. Tại mỗi thời điểm thực hiện chương trình mỗi bit đươc nhận giá trị xác định. Moi số nguyên trong máy đều biểu diễn dưới dạng nhị phân, thí dụ số 19 được biểu diễn như sau:
Bit 7 6 5 4 3 2 1 0
Giá trị 0 0 0 1 0 0 1 1 (số 19)
* Các phép toán logic
Các phép toán sau đây thực hiện trên các giá trị nguyên và cho kết quả là các giá trị nguyên.
1. Phép đảo bit Not: đổi giá trị của mọi bit từ 0 thành 1 và ngược lại. Trong C phép đảo được kí hiệu là ~ .Ví dụ

char x, y; x=19; //x=00010011// y=~x; //y=11101100(236)//

2. Phép cộng logic trên các bit (OR) thực hiện trên từng cặp bit tương ứng của các toán hạng theo bảng cộng sau:

a    b                 a  OR b 0    0                     0 0    1                     1 1    0                     1 1    1                     1

Quy tắc: Tổng hai bit bằng 0 khi và chỉ khi cả hai bit bằng 0 ngoài ra tổng nhận giá trị 1;
Trong C phép OR được biểu diễn bằng kí hiệu ||
Ví dụ

char x, y, z; x= 19;//x=00010011// y= 21;//y=00010101// z= x||y;//z=00010111(23)//

3. Phép nhân logic trên các bit AND: thực hiện trên từng cặp bit tương ứng của các toán hạng theo bảng nhân sau:

a   b                  a AND b 0   0                     0 0   1                     0 1   0                     0 1   1                     1

Quy tắc: Tích hai bit bằng 1 khi và chỉ khi cả hai bit bằng 1, ngoài ra tích nhận giá trị 0.
Trong C phép AND được biểu diễn bằng kí hiệu &&
Ví dụ

char x, y, z; x=19;//x=00010011/ y=21;//y=00010101// z=x AND y;//z=00010001(17)//

4. Phép cộng loại trừ trên các bit (XOR) : thực hiện trên từng cặp bit tương ứng của các toán hạng theo bảng sau

a     b                  a XOR b 0     0                       0 0     1                       1 1     0                       1 1     1                       0

Quy tắc: tổng loại trừ của hai bit bằng 1 khi và chỉ khi hai bit đó chứa các giá trị khác nhau, ngoài ra tổng loại trừ nhận giá trị 0.
Phép toán trên cũng còn được gọ là phép so sánh khác (khác nhau là đúng, bằng nhau là sai)
Trong C không có phép toàn này. (Có bạn nào biết cách thể hiện phép XOR bằng phép AND và OR không ?)
Ví dụ

Ví dụ này chỉ là môt tả char x, y, x; x= 19;//x=00010011// y= 21;//y=00010101// Z=x XOR Y;//z=00000110(6)//

5. Phép dịch trái (Shl): x Shl i cho gái trị nhận được từ số nguyên x sau khi dịch số đó qua trái i bit.
Quy tắc: Muốn nhân 1 số với 2 ta dịch số đó qua trái 1 bit. Tổng quát, muốn nhân một sốnguyene với 2^i ta dịch số đó qua trái i bit;
x Shl i= x*n; với n=2^i
Trong C không hỗ trợ phép toán này nhưng có thể dùng phép chia nguyên cho 2^i để thực hiện
Thí dụ

Chỉ để minh họa { chả x, y; x=19;//x=00010011// y=x Shl 2;//y=01001100=x*4=76// }

6. Phép dịch phải
(Tương tự như phép dịch trái nhưng số nguyên sẽ được dịch sang phải i bit)

MỘT SỐ ỨNG DỤNG
*Ứng dụng 1(lấy bit). Viết hàm getbit(x,i) cho giá trị của bit thứ i(tính từ phải sang) của số nguyên x.

char Getbit(char x, i) { return (x Shr i) && 1; }

*Ứng dụng 2(lấy số) Viết hàm GetNum(x, j, i) cho số tạo bởi các bit tính từ trái qua phải là bit thứ j đến bit thứ i (j>=i). Thí dụ
GetNum(103,5,1)=19 vì 103=0000 0000 0110 0111
do dó GetNum(103,5,1)= 0000 0000 0001 0011 =19
Bài giải: Gọi số lượng bit của x là L(x) , trước hết ta phải hóa 0 các bit nằm ở bên trái bit thứ j. Muốn vậy ta dịch x qua trái k= L(x)-1-j bit. Sau đó ta chuyển giá trị thu được về cấu hình ban đầu tức là dịch phải k bit rồi tiếp tục dịch phải i bit để thu được số cần tìm. Hàm sizeof(x) cho ta số byte trong x. Nhân giá trị này với 8 ta sẽ được số bit trong x. Vì phép nhân 8 tương đuơng với phép dịch trái 3 bit nên sizeof(x) Shl 3 cho ta số bit trong x. Vì các bit được mã số từ phải sang trái bắt đầu từ bit 0 cho nên số hiệu cao nhất trong x sẽ là sizeof(x) Shl 3 -1

char Getnum(char x, j, i) { char k; k= (sizeof(x) Shl 3)-1-j return x Shl k Shr k Shr i; }

Đối với 2 hàm Getbit và GetNum ở trên ta sé có được một số ứng dụng như chuyển từ số tự nhiên sang biểu diễn nhị phân, thập lục phân, bát phân.
Ngoài ra dựa vào các phép toán logic cơ bản này ta có thể có một số ứng dụng khác như:
-viết hàm biểu diễn dưới dạng nhị phân mà không có số 0 thừa ở đầu
-Viết hàm đảo trật tự các bit trong 1 số ví dụ: 1011 (11) tahnhf 1101(13)
(Bài tiếp theo: Cách bật tắt các bit trong một số nguyên)

5. Phép dịch trái (Shl): x Shl i cho gái trị nhận được từ số nguyên x sau khi dịch số đó qua trái i bit.
Quy tắc: Muốn nhân 1 số với 2 ta dịch số đó qua trái 1 bit. Tổng quát, muốn nhân một sốnguyene với 2^i ta dịch số đó qua trái i bit;
x Shl i= x*n; với n=2^i
Trong C không hỗ trợ phép toán này nhưng có thể dùng phép chia nguyên cho 2^i để thực hiện
Thí dụ

</div> <div id="cviet_code_902">Chỉ để minh họa { chả x, y; x=19;//x=00010011// y=x Shl 2;//y=01001100=x*4=76// }</div> <div>

6. Phép dịch phải
(Tương tự như phép dịch trái nhưng số nguyên sẽ được dịch sang phải i bit)

MỘT SỐ ỨNG DỤNG
*Ứng dụng 1(lấy bit). Viết hàm getbit(x,i) cho giá trị của bit thứ i(tính từ phải sang) của số nguyên x.

</div> <div id="cviet_code_399">char Getbit(char x, i) { return (x Shr i) && 1; }</div> <div>

*Ứng dụng 2(lấy số) Viết hàm GetNum(x, j, i) cho số tạo bởi các bit tính từ trái qua phải là bit thứ j đến bit thứ i (j>=i). Thí dụ
GetNum(103,5,1)=19 vì 103=0000 0000 0110 0111
do dó GetNum(103,5,1)= 0000 0000 0001 0011 =19
Bài giải: Gọi số lượng bit của x là L(x) , trước hết ta phải hóa 0 các bit nằm ở bên trái bit thứ j. Muốn vậy ta dịch x qua trái k= L(x)-1-j bit. Sau đó ta chuyển giá trị thu được về cấu hình ban đầu tức là dịch phải k bit rồi tiếp tục dịch phải i bit để thu được số cần tìm. Hàm sizeof(x) cho ta số byte trong x. Nhân giá trị này với 8 ta sẽ được số bit trong x. Vì phép nhân 8 tương đuơng với phép dịch trái 3 bit nên sizeof(x) Shl 3 cho ta số bit trong x. Vì các bit được mã số từ phải sang trái bắt đầu từ bit 0 cho nên số hiệu cao nhất trong x sẽ là sizeof(x) Shl 3 -1

</div> <div id="cviet_code_1302">char Getnum(char x, j, i) { char k; k= (sizeof(x) Shl 3)-1-j return x Shl k Shr k Shr i; }</div> <div>

Đối với 2 hàm Getbit và GetNum ở trên ta sé có được một số ứng dụng như chuyển từ số tự nhiên sang biểu diễn nhị phân, thập lục phân, bát phân.
Ngoài ra dựa vào các phép toán logic cơ bản này ta có thể có một số ứng dụng khác như:
-viết hàm biểu diễn dưới dạng nhị phân mà không có số 0 thừa ở đầu
-Viết hàm đảo trật tự các bit trong 1 số ví dụ: 1011 (11) tahnhf 1101(13)

* Thủ tục Batbit(x,i) gán trị 1 cho bit thứ i trong byte x
Mô tả: Ta chuyển 1 đến vị trí i tương ứng sau đó thực hiện phép cộng logic với byte x

</div> <div id="cviet_code_510">Ví dụ này chỉ mang tính minh họa char Batbit(char x, i) { return x OR(1 Shl i); }</div> <div>

* Thu tục Tatbit(x, i) gán trị 0 cho bit thứ i trong byte
Mô tả: Ta chuyển 1 đến vị trí i tương ứng, sau đó đảo byte này để được byte có 0 ở vị trí i và 1 ở các bit còn lại, cuối cùng thực hiện phép nhân logic với byte x.

</div> <div id="cviet_code_1238">Ví dụ này chỉ mang tính minh họa Char Tatbit(char x, i) { return NOT(1 Shl i) And x; }</div> <div>

Bạn hailoc12 đã có công viết 1 bài dài về thao tác bit => xin ủng hộ 100%Xin được góp ý vô 1 chút. Về NOT, AND, OR, XOR thì C có 2 loại: thao tác logic và thao tác bit

Thao tác logic: giá trị bằng 0 được coi như là false (sai); giá trị khác 0 được coi như là true (đúng). Các toán tử là ‘!’ (NOT), ‘&&’ (AND), và ‘||’ (OR) (không có toán tử XOR logic; nhưng có thể viết bằng NOT, AND, OR)

Thao tác bit: bit 0 được coi như là false (sai); bit 1 được coi như là true (đúng). Các toán tử là ‘~’ (NOT), ‘&’ (AND), ‘|’ (OR) va` ‘^’ (XOR)

Về phép dịch bit: các toán tử là ‘>>’ (dịch qua phải) và ‘<<‘ (dịch qua trái) (tương ứng với phép dịch cho số không dấu trong hợp ngữ; C không có toán tử dịch qua phải có dấu)

Về bật / tắt / đảo bit:

X AND 0 -> 0; X AND 1 -> X: dùng để tắt bit
X OR 0 -> X; X OR 1 -> 1: dùng để bật bit
X XOR 0 -> X; X XOR 1 -> ~X: dùng để đảo bit

Chủ đề