对32位整数中的设置位进行计数的方法的说明
Explanation of a method of counting set bits in a 32-bit integer
查看此链接中的集合位计数方法,我发现以下方法
作者说:
对32位整数v中的位进行计数的最佳方法是以下内容:
v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
最好的比特计数方法只需要12次操作,即与查找表方法相同,但避免了内存和电势表的缓存未命中。它是纯平行之间的混合上面的方法和前面使用乘法的方法(在一节中关于使用64位指令计数位(,尽管它不使用64位指令。字节中设置的位数在中完成并行,并且计算字节中设置的位的总和通过乘以0x1010101并右移24位。
有没有解释一下这个方法是如何计算集合位的?
它之所以有效,是因为您可以通过一分为二、计算两半的集合位数,然后将其相加来计算集合位数的总数。也称为Divide and Conquer
范式。让我们详细介绍一下。。
v = v - ((v >> 1) & 0x55555555);
两个比特中的比特数量可以是0b00
、0b01
或0b10
。让我们试着用2位来计算这个。。
---------------------------------------------
| v | (v >> 1) & 0b1010 | v - x |
---------------------------------------------
0b00 0b00 0b00
0b01 0b00 0b01
0b10 0b01 0b01
0b11 0b01 0b10
这就是所需要的,最后一列显示了每两位对中设置位的计数。如果两位数是>= 2 (0b10)
,则and
产生0b01
,否则产生0b00
。
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
这句话应该很容易理解。在第一次运算之后,我们每两个比特中有一个集合比特的计数,现在我们每4个比特中的计数相加。
v & 0b11001100 //masks out even two bits
(v >> 2) & 0b11001100 // masks out odd two bits
然后,我们将上述结果相加,得到4位中的集合位的总数。最后一句话是最棘手的。
c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
让我们进一步打破它。。
v + (v >> 4)
它类似于第二条语句,我们以4为一组来计算集合位。我们知道,由于我们之前的操作,每个半字节都有设置位的计数。让我们看一个例子,假设我们有字节0b01000010
。这意味着第一个半字节有4比特集,而第二个半字节则有2比特集。现在我们把这些小点心加在一起。
0b01000010 + 0b01000000
它给出了第一个半字节0b01100010
中一个字节中设置位的计数,因此我们屏蔽了该数字中所有字节的最后四个字节(丢弃它们(。
0b01100010 & 0xF0 = 0b01100000
现在,每个字节都有集合位的计数。我们需要把它们加在一起。诀窍是将结果乘以具有有趣性质的0b10101010
。如果我们的数字有四个字节A B C D
,它将产生一个带有这些字节A+B+C+D B+C+D C+D D
的新数字。一个4字节的数字最多可以设置32位,可以表示为0b00100000
。
我们现在只需要第一个字节,它是所有字节中所有设置位的总和,我们通过>> 24
得到它。该算法是为32 bit
字设计的,但可以很容易地为64 bit
字修改。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 没有为自己的结构调用列表推回方法
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 有关读取 UTF-8 编码文本时 Ifstream get() 方法行为的说明 (C++)
- CMAKE 中的操作系统特定说明:操作方法
- 对32位整数中的设置位进行计数的方法的说明