Đây là một yêu cầu mà hầu như mọi người đã không mấy xa lạ. Thông thường thao tác kiểm tra dựa vào định nghĩa toán học của số chẳn và lẻ, số chẳn là số chia hết cho 2 còn số lẻ thì không. Vậy chỉ đơn giản lôi cái số cần kiểm tra ra mà chia nó cho 2 nếu kết quả có dư thì là số lẻ còn không dư thì đương nhiên là số chẳn. Tuy nhiên ở đây tôi muốn đi theo một hướng khác, nông dân nhưng hiệu quả hơn về mặt tính toán. Như chúng ta đều biết, mọi số nguyên tùy theo kiểu dữ liệu, cách quản lý của hệ điều hành mà sẽ được biểu diễn ở dạng số nhị phân trong một vùng nhớ có kích thước nào đó, ví dụ một số nguyên không dấu 4 byte có giá trị là 3 sẽ đại loại được thể hiện như thế này: 0000 0000 0000 0000 0000 0000 0000 0011. Và ta có nhận xét, ở dạng nhị phân một số là chẳn nếu bít thấp đầu tiên của nó bằng 0, là lẻ nếu bằng 1. Như vậy bài toán kiểm tra một số nguyên chẳn hay lẻ sẽ quy về kiểm tra bít đầu tiên bằng 0 hay bằng 1. Tôi thực hiện điều đó đơn giản bằng một macro với các phép toán so bít và luận lý như sau:
 
#define VNS_MACRO_IS_EVEN(x) ((x & 1) == 0)
 
Khi x = 3 vậy (x & 1) tương đương với:
 
0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 0001
-------------------------------------------------------
0000 0000 0000 0000 0000 0000 0000 0001 = 1

 
tiếp đó (1 == 0) đương nhiên sẽ trả về 0 (false), do vậy VNS_MACRO_IS_EVEN(3) sẽ bằng 0 (false) hay 3 là số lẻ.
 
if( VNS_MACRO_IS_EVEN(3) )
{
   printf("so chan");
}else{
   printf("so le");
}
 
chương trình sẽ in chuỗi: "so le".
 
Bài viết này nói về một bài toán nhỏ, quen thuộc mà thậm chí cũng chẳng ai coi nó là một bài toán cả, nhưng qua đó tôi muốn nhắc lại một vài thứ có thể hay bị lãng quên (các xử lý trên bít) và hy vọng  mang tới cho những người mới cái tư tưởng: thành công của một xử lý không chỉ nằm ở tính đúng của kết quả mà còn nằm ở hiệu năng, sự tinh tế của nó.

-- BIOZ --