30/09/2018, 17:52

Các kĩ thuật thao tác trên bit có ứng dụng gì?

Xin chào mọi người…mình đang học về C/C++ đến phần: Các thao tác trên bit và có 1 câu hỏi mình thắc mắc mong mọi người trợ giúp là: Các kĩ thuật thao tác trên bit có ứng dụng gì. Có phải dùng trong lập trình phần mềm hệ thống không? Nếu như lập trình phần mềm ứng dụng hay game thì có cần dùng không? Thank

Nguyễn Văn Tâm viết 20:01 ngày 30/09/2018

Nó cũng giống như các phép toán khác thôi, ứng dụng gì thì phải tùy vào thực tế chứ bạn. Các thao tác trên bit có tốc độ rất nhanh.

Ngo Dinh Quyen viết 20:05 ngày 30/09/2018

Bạn nói rõ hơn được không

Mai Anh Dũng viết 19:55 ngày 30/09/2018

Xem câu trả lời này xem, nó có rất nhiều ví dụ đấy

stackoverflow.com
non sequitor

What USEFUL bitwise operator code tricks should a developer know about?

design, language-agnostic, bit-manipulation, bit
asked by non sequitor on 05:44PM - 07 Oct 09
Minh Hoàng viết 19:54 ngày 30/09/2018

Thao tác trên bit thì có tốc độ khá cao, nhưng ứng dụng thì mình nghĩ hạn chế
Bạn có thể đọc tài liệu Bit twiddling Hack, nó có khá nhiều “trick” thao tác trên bit.
Mình nghĩ lập trình ứng dụng thì không cần đâu. Lập trình game thì các hiệu ứng có lẽ cần.

Hung viết 19:57 ngày 30/09/2018

Mình thấy ứng dụng nhiều trong lập trình nhúng.
Còn đơn giản nhất là ứng dụng trong lập trình vi điều khiển với đèn led: chớp nháy, đèn sáng vòng vòng theo ý mình cho ra nhiều hình rất đẹp.
Các bảng quảng cáo bằng led mà bạn thấy ngoài phố, cũng là ứng dụng của lập trình thao tác trên bit sử dụng ngôn ngữ C.

Ngo Dinh Quyen viết 19:56 ngày 30/09/2018

Cảm ơn, mình sẽ tìm hiều theo gợi ý của các bạn

Chi Ngo viết 19:53 ngày 30/09/2018

Mình không làm C/C++ nhiều nhưng thấy rất nhiều ví dụ. Chẳng hạn như thế này, bài toán có nhiều lựa chọn:
OPTION_A làm việc A
OPTION_B làm việc B
OPTION_C làm việc C
OPTION_D làm việc D
Lúc này, chúng ta truyền vào OPTION_A thì chỉ làm việc A, OPTION_X chỉ làm việc X. Nhưng nếu ta lại muốn truyền cả vào OPTION_A và OPTION_C thì phải làm thế nào? Lúc này rõ ràng ta sẽ nghĩ đến phép toán OR.
Ta cho OPTION_A=1, OPTION_B=2, OPTION_C=4 và OPTION_D = 8.
Khi đó, truyền vào giá trị là 5 thì rõ ràng 5 OR 1 = 1, 5 OR 2 = 0, 5 OR 4 = 1 và 5 OR 8 = 0. Do đó, chỉ có 2 OPTION_A và và OPTION_C là hoạt động mà thôi.
Một ví dụ phổ biến phải không?

Ngo Dinh Quyen viết 19:59 ngày 30/09/2018

ví dụ khó quá…chắc mình phải học thêm mới hiểu được…

viết 20:05 ngày 30/09/2018

ví dụ cho dễ hiểu là ở fstream có các mode: in, out, binary, ate, app, trunc. Mỗi mode là 1 biến bool, true/false.

vd fstream fin có in=true, out=false, binary=true, ate=false, app=false, trunc=false thì fin là file nhị phân chỉ để đọc.

Bây giờ nếu fstream có 6 biến bool thì tốn hết 6 bytes bộ nhớ, khá lãng phí vì boolean chỉ cần 1 bit là đủ, thay vì cần tới 1 byte = 8 bit. Hơn nữa nếu cần tới 6 biến riêng biệt thì khi viết hàm khởi tạo cho fstream sẽ cần truyền hết 6 flag này vào:

//mặc định là file chỉ để đọc
fstream(const char* filename, bool in=true, bool out=false, bool binary=false, bool ate=false, bool app=false, bool trunc=false);

viết như vậy là cực kì dài dòng. Hơn nữa khi đọc code khởi tạo 1 object fstream cụ thể cũng chả hiểu file mode của nó là gì, nếu ko nhớ định nghĩa của hàm khởi tạo fstream:

fstream fin("binary_input.txt", true, false, true); //cái gì true cái gì false?? mode nào được set true ở đây??

.
.
.
nếu gộp chung 6 flag này vào 1 biến int duy nhất (biến int có 32 bit, dư sức chứa 6 biến bool chỉ cần 6 bit ở đây) thì hàm khởi tạo chỉ đơn giản có thêm 1 flag file mode:

//mặc định là file chỉ để đọc
fstream(const char* filename, int filemode=fstream::in);

ở đây vd ta chọn bit đầu tiên là flag của in, bit thứ hai là flag của out, v.v…, bit thứ sáu là flag của trunc. Vậy ta sẽ định nghĩa các hằng số file mode như sau:

fstream::in     = 1;      //000001 (nhị phân)
fstream::out    = 1 << 1; //000010
fstream::binary = 1 << 2; //000100
fstream::ate    = 1 << 3; //001000
fstream::app    = 1 << 4; //010000
fstream::trunc  = 1 << 5; //100000

để gộp các flag lại với nhau ta dùng logical OR, hay là operator | trong C/C++:

fstream fin("binary_input.txt", fstream::in | fstream::binary); //thấy rõ file mode là input và binary, quá tốt

fstream::in | fstream::binary sẽ cho ra số 000101 ở hệ nhị phân, hay là số 5 ở hệ thập phân. Hàm khởi tạo sẽ nhận được flag filemode này, mang giá trị 5, và sẽ tách các thuộc tính của file ra bằng cách xài logical AND (operator & trong C/C++):

bool is_in     = filemode & fstream::in; //int cast về bool đơn giản: giá trị khác 0 là true, bằng 0 là false
bool is_out    = filemode & fstream::out;
bool is_binary = filemode & fstream::binary;
bool is_ate    = filemode & fstream::ate;
bool is_app    = filemode & fstream::app;
bool is_trunc  = filemode & fstream::trunc;

000101 & 000001 = 000001: khác 0 nên is_in = true
000101 & 000010 = 000000: bằng 0 nên is_out = false
000101 & 000100 = 000100: khác 0 nên is_binary = true
000101 & 001000 = 000000: bằng 0 nên is_ate = false
v.v…

ở đây chỉ có 6 flags, thử 1 class có 10 flags 20 flags 30 flags thì nín thở mà truyền hết các flag này theo cách 1. Cách 2 dù có 30 flags thì cũng chỉ cần truyền 1 số duy nhất.
.
.
.
.
.
.
.
ngoài ra kỹ thuật thao tác trên bit còn được dùng để tránh phân nhánh code (sử dụng if), vì 1 dòng phân nhánh thì chậm hơn 1 dòng code tính toán bình thường từ khoảng vài chục phần trăm tới vài lần. Ví dụ đơn giản nhất là viết hàm tính trị tuyệt đối của 1 số thực, vd là float x. Bình thường có thể viết

if (x < 0) return -x;
return x;

như vậy phải xài 1 lần phân nhánh. Nếu biết là chỉ có bit đầu tiên của float là quyết định tới dấu của x, các bit còn lại ko ảnh hưởng thì ta chỉ cần chuyển bit này thì bit 0, hay số dương là được:

int y = *( (int*) &x ); //cast x từ float thành int mà vẫn giữ nguyên các bit
y &= 0x7fffffff; //gán y = y & 0111111...111 thì tất cả các bit đều giữ nguyên giá trị ban đầu trừ bit đầu tiên bị set thành 0
return *( (float*) &y ); //cast y từ int thành float lại mà vẫn giữ nguyên các bit

ở đây ta ko cần biết x âm hay dương, cứ set nó thành dương hết, ko cần phân nhánh, nhanh hơn từ vài chục phần trăm tới vài lần.

còn nhiều ứng dụng trong computer graphics nữa, gu gồ đi ta cũng chưa đụng tới

Ngo Dinh Quyen viết 20:01 ngày 30/09/2018

gu gồ đi ta cũng chưa đụng tớ

Hoa mắt quá bác ơi…

minh tran viết 19:57 ngày 30/09/2018

Bitwise này dùng nhiều nhất trong lập trình nhúng, các thao tác trên register rất cần bitwise
Ví dụ như muốn set bit thứ 10 của register
Nếu ko dùng bitwise thì phải ghi là A = 0000000001000000

Nếu dùng bítwise đơn giản chỉ là A |= (1<<9)

Comment bằng điện thoại nên trình bày ko đẹp mong bạn thông cảm.

Ngo Dinh Quyen viết 19:52 ngày 30/09/2018

Dung điện thoại vào Daynhauhoc ạ…bạn chăm quá…

Tan viết 20:08 ngày 30/09/2018

Ví dụ của bác dễ hình dung. Tuy nhiên tại hạ nghĩ là dùng toán tử AND sẽ chính xác hơn là OR.

Tan viết 19:53 ngày 30/09/2018

Cảm ơn bác. Ví dụ hay quá. Qua đó em còn biết thêm rằng có thể chuyển từ số float sang số int. Hay thật.

Bài liên quan
0