简体   繁体   中英

Bit manipulation: detect if at least 5 bits in byte are set?

What is the best way to check if a minimum number of bits have been set in a binary number?

For example I need to see if at least 5 bits are set to 1 in this sequence:

101100010

I've been looking at using bit masks and the like but am more confused than confident about how this can be done.

Any help appreciated.

From http://blog.faultylabs.com/2011.php?p=jsbitfun

/*
 popCnt(n)
 Returns the bit population count of n (that is: how many bits in n are set to 1)
 n must be an unsigned integer in the range [0..(2^32)-1]
 This lookup-table-free method is from Kernighan & Ritchie's "The C Programming Language"
 Exercise 2.9 (on page 62 of my copy). Not sure whether they (K&R) are the inventors.
*/
function popCnt(n) {
    n >>>= 0 /* force uint32 */
    for(var popcnt = 0; n; n &= n - 1) {
        popcnt++
    }
    return popcnt
}

See http://en.wikipedia.org/wiki/Hamming_weight for details on other algorithms.

If you are trying to learn to work with bits, play around with bitmasks.

If you need a very simple solution just convert the integer to a string representation of its binary value and count number of 1's:

var i = 0x1 +0x4 + 0x8 +0x80; // 10001101 in binary
var numberOf1s = i.toString(2).split('1').length-1; // 4

so all in all you need just a single line of code to do it:

if(<insert your var>.toString(2).split('1').length-1 >=5) {
  //At least 5 bits are set
}

Do it with bitmasks first, especially if trying to learn. It's the most logically simple approach when looking at it as a sequence of bits. (There are a bunch of clever tricks that can be done, but first is first and, with a language like JS with a myriad of engines, the implementation might make clever-not-so-clever.)

To test if bit b is set, it is set when input & (1 << b) is non-0, of course 1 << b is 00000001 (0x01), 00000010 (0x02), 00000100 (0x04), 00001000 (0x08) and so-on when b is 0, 1, 2, 3 and so-on. (Note 1 is 00000001 and how << moves the pattern left by b bits).

So, for each 0 <= b < 8, see if the bit is set. If it is, add one to a counter.

Now we know how many bits in the first octect are set.

Also note that there is only a small finite set of values for b we care about. Thus we can eliminate the loop and know each 1 << b for each loop iteration. (Some browsers like Firefox can process a sequence of bit-wise math operations like this very very fast when a single expression.)

Happy coding


For fun I decided to create a quick performance test-case of popCnt (and strCount ), as shown in other answers, and a specialized bit-counter, fastCount8 , that only uses math operations and doesn't try to be overly clever and a simpleCount8 as described above.

Granted that both fastCount8 (and simpleCount8 ) are limited to a single octect (first byte), but for this particular case fastCount8 is very much faster in certain browsers. (It is significantly faster in FF8 but only marginally faster in IE9 and slower in Chrome 16.) As expected, strCount is substantially slower than popCnt and simpleCount8 doesn't fair much better.

Here is the jsperf test , and fastCount8 :

function fastCount8(n) {
    // >> has higher precedence than &
    return (n >> 0 & 1)
      + (n >> 1 & 1)
      + (n >> 2 & 1)
      + (n >> 3 & 1)
      + (n >> 4 & 1)
      + (n >> 5 & 1)
      + (n >> 6 & 1)
      + (n >> 7 & 1)
}

Updated performance test-cases for lookup8 , lookupN (and some variants), fastCount8N and fastCount8N2 . The results are quite spectacular: FF8 does some absolutely amazing math optimizations and the other browsers (I tested) can't even come close to keeping up for the given expression. Also, the other results can be somewhat surprising and showcase how different browsers optimize different things...

...all in all, lookup8 and lookupN2b look the most consistent across browsers... at least with the given range of n applied.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM