0% found this document useful (0 votes)
153 views

Bit Mask

Bitmasks provide an efficient way to represent subsets of a set by using each bit in an integer to indicate whether an element is included or not. Common bitwise operators allow easy manipulation of bitmasks, such as setting, clearing, and checking bits. While compact, bitmasks are limited by the size of the data type used, and care must be taken to select the proper type based on set size and operator precedence.

Uploaded by

Alexander Mejia
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
153 views

Bit Mask

Bitmasks provide an efficient way to represent subsets of a set by using each bit in an integer to indicate whether an element is included or not. Common bitwise operators allow easy manipulation of bitmasks, such as setting, clearing, and checking bits. While compact, bitmasks are limited by the size of the data type used, and care must be taken to select the proper type based on set size and operator precedence.

Uploaded by

Alexander Mejia
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 2

Using Bitmask 1 Motivation

Suppose you have a set of objects and you want some way to represent which objects to pick and which ones not to pick. How do you represent that in in a program? More generally, how do you represent a subest of a set?One way is to use a Map to associate with each object a boolean value indicating whether the object is picked. Alternatively, if the object can be indexed by integers, you can use a boolean array. However, this takes up a lot of memory and can be slow due to the overhead of Map and array. If the size of the set is not too large, a bitmask is much more efcient (and convenient)!

What is a Bitmask?

We can represent whether an object is picked or not by a single bit! Using a boolean to represent this is an overkill in terms of memory usage. However, neither C++ nor Java has any data type representing a single bit, so how can we cut down the memory usage? The answer is to use an integer! We know an integer is just a bunch of bits stringed together, so why dont we use the integer to represent the entire set? The 1st bit will represent whether the 1st object is picked, the 2nd bit will represent whether the 2nd object is picked or not, etc. For example, suppose in a set of 5 objects, we have picked the 1st , 3rd , and 4th object. The bitmask to represent this in binary is 01101 or 13 in decimal (in the notes, the 1st bit will always be the least signicant bit and will always appear at the very right). We have just cut down the memory usage from ve booleans to a single integer! This sounds nice, but there is a serious limitation to this approach. An int is 32-bit, so what if the number of objects is greater than 32? In this case, we will have to use a long long in C++ or long in Java. So what if the number of object is greater than 64? Unfourtunately, bitmask becomes infeasible.

Manipulating Bitmask

Bitmask are not only memory efcient, they are also easy to manipulate. Both C++ and Java supports a variety of bitwise operators: Bitwise Operators Operator >> << & | Name Right Shift Description Shift every bit to the right, discard the lowest signicant bit, and extend the sign bit Left Shift Shift every bit to the left, discard the highest signicant bit (sign is preserved), and add a 0 as the lowest signicant bit Bitwise And And every bit individually Bitwise Or Or every bit individually Bitwise Xor Xor every bit individually Bitwise Not Flip every bit Example -8 >> 3 = -1 -8 << 1 = -16 9 & 3 = 1 9 | 3 = 11 9 3 = 10 9 = -10

With these operations, we can manipulate the bitmask in many ways: Description Add the ith object to the subset (set the ith bit from 0 to 1) Remove the ith object from the subset (set the ith bit from 1 to 0) Check whether the ith object is in the subset (check whether ith bit is 1) Iterate through all subsets of a set of size n Iterate through all subsets of a subset y (not including empty set) Find the lowest index that is set to 1 Code x = (x | (1 << i)) x = (x - (1 << i)) (x & (1 << i)) != 0 for (x = 0; x < (1 << n); ++x) for (x = y; x > 0; x = (y & (x-1))) x & (-x)

Final Remarks

Bitmask is an efcient and convenient way to represent subsets. For example, given a set of numbers, we want to nd the sum of all subsets. This is easy to code using bitmasks. Furthermore, we can use an array to store all the results (imagine storing the results when you are using an array to represent the subset)! i n t s u m o f a l l s u b s e t ( v e c t o r <i n t > s ) { int n = s . size ( ) ; i n t r e s u l t s [ ( 1 << n ) ] ; / / i n i t i a l i z e r e s u l t s to 0 memset ( r e s u l t s , 0 , s i z e o f ( r e s u l t s ) ) ; / / i t e r a t e through a l l subsets f o r ( i n t i = 0 ; i < ( 1 << n ) ; ++ i ) { for ( int j = 0; j < n ; ++ j ) { i f ( ( i & ( 1 << j ) ) ! = 0 ) r e s u l t s [ i ] += s [ j ] ; } } } Finally, two word of caution on using bitmasks. First, always check the size of the set to determine whether to use an int or long long (long in Java) or not using bitmask at all. Secondly, always use parenthesis to indicate the precedence of operations when doing bitwise operations! The order of operations is very screwed up when it involves bitwise operators and not putting parenthesis when yield undesirable results! For example, let x = 5. Then x - 1 << 2 = 16, but x - (1 << 2) = 1.

You might also like