vogel's blog

By vogel, 8 years ago, translation, In English

Now I am writing an article about bit manipulation, bit magic and other trciks for wiki — conspects (This is a great resource of algorithms in Russian). If you know some useful bit tricks, which used in algoritms or just funny things connected with bits write them in comments below. Also you are welcomed with really strange, weird and sophisticated solutions for well-known problems. For example: swapping values with XOR.

Good style for your comments:

  • Descripotion of the problem
  • Solution of the problem in code with short explanation for tricky moments

Example of a perfect comment:
Determining if an integer is a power of 2

unsigned int v; // we want to see if v is a power of 2
bool f;         // the result goes here 

f = (v & (v - 1)) == 0;

Short explanation: Let v — power of two (this is one and k zeros in binary presentation) and v — 1 is k ones in binary presenation. Then notice that bitwise AND v and v — 1 must be 0.

Warm — up problem: Find smallest 1 — bit (not zero) in O(1)

  • Vote: I like it
  • +50
  • Vote: I do not like it

| Write comment?
»
8 years ago, # |
  Vote: I like it +37 Vote: I do not like it

Zero is not a power of two. Your code says otherwise :)

»
8 years ago, # |
Rev. 2   Vote: I like it 0 Vote: I do not like it

or:
f = __builtin_popcount(v) == 1;

»
8 years ago, # |
  Vote: I like it +23 Vote: I do not like it

Smallest bit set to 1 of an integer

int bit = number & -number;

Explanation: -number representation using 2-complement keeps the smallest 1-bit and inverts the other most significative bits.

Unsetting the smallest 1-bit of an integer

int number = 123; number -= number & -number;

Counting the number of bits set to 1

int amount = 0;
for (; number > 0; number -= number & -number)
  ++amount;

Toggle bit i from 1->0 or 0->1

number ^= 1 << i;

Xor with bit set to 1, makes it change its value, whereas the other bits are 0 and don't change anything.

Iterate all subsets of a bitmask in increasing order

for ( int sub = 0 ; sub = sub - bitmask & bitmask ; ) {
  // do something
}

Iterate all subsets of a bitmask in decreasing order

for(int sub = (mask-1) & bitmask ; sub > 0 ; sub = (sub-1) & bitmask )  {
  // do something 
}
  • »
    »
    8 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Can u plz give a small example for "Iterate all subsets of a bitmask in increasing order". It is not clear to me... :/

»
8 years ago, # |
Rev. 12   Vote: I like it -37 Vote: I do not like it

Swap two integers

a ^= b ^= a ^= b;

Check whether two integers are equal or not:

if (a ^ b) // they aren't equal!

Check if a equals -1 or not

if (~a) // a != -1

Get the largest number I can!

int (or long long) INF = -1ull/2;

For the least number

int (or long long) LEAST = ~(-1ull/2);
»
8 years ago, # |
  Vote: I like it 0 Vote: I do not like it

Operation x & (x — 1) sets rightmost 1 to 0. As powers of 2 have only one 1 — it can be used to check them.

»
8 years ago, # |
  Vote: I like it +3 Vote: I do not like it

My favorite is binary searching by bit manipulation — no off-by-1 errors!

/**
   * Binary search by bit toggling from MSB to LSB
   * O(64) bit-wise operations for Longs (O(32) for Ints)
   *
   * @return Some(x) such that x is the largest number for which f is true
   *         If no such x is found, None
   */
  def bitBinSearch(f: Long => Boolean): Option[Long] = {
    var p = 0L
    var n = Long.MinValue
    var t = n >>> 1
    while (t > 0) {
      if (f(p|t)) p |= t
      if (f(n|t)) n |= t
      t >>= 1
    }
    Seq(p, n) find f
  }

Original source: https://github.com/pathikrit/scalgos/tree/master/src/main/scala/com/github/pathikrit/scalgos

  • »
    »
    8 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Could you explain please what Seq(p, n) find f means?

    • »
      »
      »
      8 years ago, # ^ |
      Rev. 3   Vote: I like it +4 Vote: I do not like it

      p and n are numbers in [0, Long.MaxValue] and [Long.MinValue, 0] respectively for which f maybe satisfactory. Seq(p, n) creates a sequence of these 2 numbers and Seq(p, n) find f returns the first one for which f is true else None. I am using Scala as my language; here's a Java/C++-ish version (not tested):

      long p = 0L, n = Long.MinValue;
      for (long t = n >>> 1; t > 0; t >>= 1) {
        if (f(p|t)) p |= t;
        if (f(n|t)) n |= t;
      }
      if (f(p)) return p;
      if (f(n)) return n;
      return null;
      
»
6 years ago, # |
  Vote: I like it +1 Vote: I do not like it

Can someone provide links to the problems, where you need a fast way to count number of 1's in mask or index of last setted bit?