I must say I have never had cause to use bitwise operators, but I am sure there are some operations that I have performed that would have been more efficiently done with them. How have "shifting" and "OR-ing" helped you solve a problem more efficiently?
views:
378answers:
10Check out this links. It's for actionscript but bitwise operators are pretty much the same as in other languages: bitwise gems fast integer math
1) Divide/Multiply by a power of 2
foo >>= x;
(divide by power of 2)
foo <<= x;
(multiply by power of 2)
2) Swap
x ^= y;
y = x ^ y;
x ^= y;
I have not read the book (yet), but I have been told that the Book Hacker's Delight shows a number of tricks in working with bits.
While multiplying/dividing by shifting seems nifty, the only thing I needed once in a while was compressing booleans into bits. For that you need bitwise AND/OR, and probably bit shifting/inversion.
You can compress data, e.g. a collection of integers:
- See which integer values appear more frequently in the collection
- Use short bit-sequences to represent the values which appear more frequently (and longer bit-sequences to represent the values which appear less frequently)
- Concatenate the bits-sequences: so for example, the first 3 bits in the resulting bit stream might represent one integer, then the next 9 bits another integer, etc.
I used bitwise operators to efficiently implement distance calculations for bitstrings. In my application bitstrings were used to represent positions in a discretised space (an octree, if you're interested, encoded with Morton ordering). The distance calculations were needed to know whether points on the grid fell within a particular radius.
Counting set bits, finding lowest/highest set bit, finding nth-from-top/bottom set bit and others can be useful, and it's worth looking at the bit-twiddling hacks site.
That said, this kind of thing isn't day-to-day important. Useful to have a library, but even then the most common uses are indirect (e.g. using a bitset container). Also, ideally, these would be standard library functions - a lot of them are better handled using specialise CPU instructions on some platforms.
See the famous Bit Twiddling Hacks
Most of the multiply/divide ones are unnecessary - the compiler will do that automatically and you will just confuse people.
But there are a bunch of, 'check/set/toggle bit N' type hacks that are very useful if you work with hardware or communications protocols.
I wanted a function to round numbers to the next highest power of two, so I visited the Bit Twiddling website that's been brought up several times and came up with this:
i--;
i |= i >> 1;
i |= i >> 2;
i |= i >> 4;
i |= i >> 8;
i |= i >> 16;
i++;
I use it on a size_t
type. It probably won't play well on signed types. If you're worried about portability to platforms with different sized types, sprinkle your code with #if SIZE_MAX >= (number)
directives in appropriate places.
There's only three that I've ever used with any frequency:
Set a bit: a |= 1 << bit;
Clear a bit: a &= ~(1 << bit);
Test that a bit is set: a & (1 << bit);