C 代码计算“1”的数量 无符号字符中的位
我需要 C 代码来返回 C 中无符号字符中 1 的数量。如果不明显,我需要解释为什么它可以工作。 我找到了很多 32 位数字的代码,但没有找到太多用于无符号字符的代码。
I need C code to return the number of 1's in an unsigned char in C. I need an explanation as to why it works if it's not obvious. I've found a lot of code for a 32-bit number but not much for an unsigned char.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
有一个知道 0 到 15 位数的数组。将每个半字节的结果相加。
Have an array that knows the number of bits for 0 through 15. Add the results for each nibble.
相同的代码适用于无符号字符。 循环测试它们的所有位。 请参阅此。
The same code will work for an unsigned char. Loop over all bits testing them. See this.
HACKMEM 在 3 个操作中使用此算法(大致翻译为 C) :(
ULL
是强制64位算术。这是需要的,只是勉强......这个计算需要33位整数。)实际上,你可以用
042104210021ULL替换第二个常量
code>,因为你只计算 8 位,但它看起来不太对称。这是如何运作的? 按位思考
c
,并记住(a + b) % c = (a % c + b % c) % c
和(a | b) == a + b
当且仅当(a & b) == 0
。如果您没有可用的 64 位算术,您可以将
c
分成半个字节并分别执行一半,需要 9 次运算。 这仅需要 13 位,因此使用 16 位或 32 位算术即可。例如,如果
c == 105 == 0b11001001
,HACKMEM has this algorithm in 3 operations (roughly translated to C):
(
ULL
is to force 64-bit arithmetic. It's needed, just barely... this calculation requires 33-bit integers.)Actually, you can replace the second constant with
042104210021ULL
, since you're only counting 8 bits, but it doesn't look as nicely symmetrical.How does this work? Think of
c
bit-wise, and remember that(a + b) % c = (a % c + b % c) % c
, and(a | b) == a + b
iff(a & b) == 0
.If you don't have 64-bit arithmetic available, you can split
c
up into nibbles and do each half, taking 9 operations. This only requires 13 bits, so using 16- or 32-bit arithmetic will work.For example, if
c == 105 == 0b11001001
,请参阅位旋转黑客页面:http://graphics.stanford.edu/~seander/ bithacks.html#CountBitsSetKernighan
对于这个问题有很多好的解决方案。
此外,这个函数在其最简单的实现中是相当简单的。 您应该花时间学习如何执行此操作。
See the bit twiddling hacks page: http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
there are many good solutions for this.
Also, this function in its simplest implementation is fairly trivial. You should take the time to learn how to do this.
对于像无符号字符一样小的整数,您可以使用小型查找表获得最佳性能。
我知道你提到的人口计数算法。 它们的工作原理是对小于寄存器中存储的整数的多个字进行算术。
这种技术称为 SWAR (http://en.wikipedia.org/wiki/SWAR) 。
欲了解更多信息,我建议您查看 hackersdelight 网站:www.hackersdelight.org。 他有示例代码并写了一本书,详细解释了这些技巧。
For a integer as small as an unsigned char you get best performance using a small lookup-table.
I know what population-count algorithms you're mentioning. They work by doing arithmetic of multiple words smaller than an integer stored in a register.
This technique is called SWAR (http://en.wikipedia.org/wiki/SWAR).
For more information I suggest you check out the hackers delight website: www.hackersdelight.org. He has example code and written a book that explains these tricks in detail.
正如已经回答的那样,计算位的标准方法也适用于无符号字符。
例子:
As already answered, the standard ways of counting bits also work on unsigned chars.
Example:
unsigned char 是一个“数字”,就像 32 位浮点数或整数是一个“数字”一样,编译器认为它们代表的就是变化。
如果你把一个字符想象成它的位:
01010011(8位);
您可以通过执行以下操作来计算设置的位:
取值,假设为 x,并取 x % 2,余数将为 1 或 0。也就是说,取决于 char 的字节顺序,最左边或最右边少量。 将余数累加到一个单独的变量中(这将是设置位数的结果)。
然后>> (右移)1 位。
重复直到 8 位被移位。
从我的伪代码中实现 c 代码应该非常简单,但基本上
an unsigned char is a "number" in just the same way that a 32-bit float or integer is a "number", what the compiler deems them to represent is what changes.
if you picture a char as its bits:
01010011 (8 bits);
you can count the set bits by doing the following:
take the value, lets say x, and take x % 2, the remainder will be either 1 or 0. that is, depending on the endianness of the char, the left or right most bit. accumulate the remainder in a separate variable (this will be the resulting number of set bits).
then >> (right shift) 1 bit.
repeat until 8 bits have been shifted.
the c code should be pretty simple to implement from my pseudocode, but basically
根据 Ehemient 的帖子,我们有无分支的 8 位版本。 它以十六进制表示。
应用两次,我们有16位版本,需要9次操作。
这里我写了一个变体16位版本,需要64位寄存器和11次操作。 看起来并不比前一个好,但它只是使用了 1 模运算。
base on Ephemient's post, we have the no branched 8 bits version. It is in hexadecimal expression.
Apply it twice, we have a 16bits version, which needs 9 operations.
Here I write a variant 16bits version which needs 64bits registers and 11 operations. It seems not better than the previous one, but it just uses 1 modulo operation.