简体   繁体   English

位操作:检测字节中是否设置了至少5位?

[英]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: 例如,我需要查看此序列中是否至少将5位设置为1:

101100010 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 来自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. 有关其他算法的详细信息,请参见http://en.wikipedia.org/wiki/Hamming_weight

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: 如果您需要一个非常简单的解决方案,只需将整数转换为其二进制值的字符串表示形式,并计算1的计数:

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.) (现在有很多可以做聪明的把戏,但首先是第一和,与发动机无数像JS语言,实现可能使聪明,不那么聪明。)

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. 为了测试是否设置了位b ,当input & (1 << b)非0时,它被设置,当然1 << b00000001 (0x01), 00000010 (0x02), 00000100 (0x04), 00001000 (0x08) )当b为0,1,2,3等等时,等等。 (Note 1 is 00000001 and how << moves the pattern left by b bits). (注1是00000001以及<<如何将模式左移 b位)。

So, for each 0 <= b < 8, see if the bit is set. 因此,对于每个0 <= b <8,查看该位是否已设置。 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. 还要注意,我们关心的b只有一小组有限的值。 Thus we can eliminate the loop and know each 1 << b for each loop iteration. 因此,我们可以消除循环并知道每个循环迭代的每个1 << b (Some browsers like Firefox can process a sequence of bit-wise math operations like this very very fast when a single expression.) (像Firefox这样的浏览器在单个表达式时可以非常快速地处理一系列逐位数学运算。)

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. 为了好玩,我决定创建一个popCnt (和strCount )的快速性能测试用例,如其他答案所示,以及一个专门的位计数器fastCount8 ,它只使用数学运算而不会过于聪明。 simpleCount8如上所述。

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. 假设fastCount8 (和simpleCount8 )都限制为单个八位字节(第一个字节),但对于这种特殊情况, fastCount8某些浏览器中速度要快得多。 (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. (它在FF8中明显更快,但在IE9中仅popCnt快一些,在Chrome 16中速度更慢 。)正如预期的那样, strCountpopCnt慢得多,而simpleCount8则不popCnt

Here is the jsperf test , and fastCount8 : 这是jsperf测试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 . 更新了lookup8lookupN (和一些变体), fastCount8NfastCount8N2 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. 结果非常壮观:FF8做了一些绝对惊人的数学优化,其他浏览器(我测试过)甚至无法接近保持给定的表达式。 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. ...总而言之, lookup8lookupN2b在浏览器中看起来最一致......至少在给定的n范围内。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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