[英]Can someone explain how this bitCount code works?
这是我的助教帮助我获得的代码,但后来我完全忘记了它是如何工作的,因为我似乎无法获得正确的答案,面试成绩将于明天开始。 如果有人可以帮忙,请做。 谢谢
* bitCount - returns count of number of 1's in word
* Examples: bitCount(5) = 2, bitCount(7) = 3
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 40
* Rating: 4
*/
int bitCount(int x) {
int m4 = 0x1 | (0x1<<8) | (0x1<<16) | (0x1<<24);
int m1 = 0xFF;
int s4 = (x&m4) + ((x>>1)&m4) + ((x>>2)&m4) + ((x>>3)&m4) + ((x>>4)&m4) + ((x>>5)&m4) + ((x>>6)&m4) + ((x>>7)&m4);
int s1 = (s4&m1) + ((s4>>8)&m1) + ((s4>>16)&m1) + ((s4>>24)&m1);
return s1;
}
将其转换为位表示形式时,通常更容易看到与位相关的操作中发生的情况:
假设int为32位,则以下是m4和m1的位表示形式:
0000 0001 0000 0001 0000 0001 0000 0001 //m4, masking across the 4 bytes
0000 0000 0000 0000 0000 0000 1111 1111 //m1, masking only 1 byte, the Least Significant Byte (LSB)
我想m代表mask ,而4&1分别代表4个字节和1个字节
然后棘手的部分是s4。 您可能需要逐步检查它以了解它的含义。
首先,请注意右移和m4的掩蔽:
pqrs tuvw pqrs tuvw pqrs tuvw pqrs tuvw // x
0000 0001 0000 0001 0000 0001 0000 0001 //m4
---------------------------------------- &
0000 000w 0000 000w 0000 000w 0000 000w //x&m4
pqrs tuvw pqrs tuvw pqrs tuvw pqrs tuvw // x
---------------------------------------- >> 1
0pqr stuv wpqr stuv wpqr stuv wpqr stuv // x >> 1
0000 0001 0000 0001 0000 0001 0000 0001 //m4
---------------------------------------- &
0000 000v 0000 000v 0000 000v 0000 000v //(x>>1)&m4
.
.
pqrs tuvw pqrs tuvw pqrs tuvw pqrs tuvw // x
---------------------------------------- >> 7
0000 000p qrst uvwp qrst uvwp qrst uvwp // x >> 7
0000 0001 0000 0001 0000 0001 0000 0001 //m4
---------------------------------------- &
0000 000p 0000 000p 0000 000p 0000 000p //(x>>7)&m4
其次,请注意从以上结果中获得的8个元素的加法:
0000 000w 0000 000w 0000 000w 0000 000w //x&m4
0000 000v 0000 000v 0000 000v 0000 000v //(x>>1)&m4
.
.
0000 000p 0000 000p 0000 000p 0000 000p //(x>>7)&m4
---------------------------------------- +
//Resulting in s4
因此,由于p到w各自只能为0或1,并且您拥有八个这样的元素,因此,每8位段中您具有:
p+q+r+s+t+u+v+w // each element is either 0 or 1
从那里可以清楚地看到,以上添加的8个元素的结果范围为0到8。
也就是说,每8位段将获得0000 0000(十进制表示为0-如果全为0)到0000 1000(十进制表示为8-如果全为1)。
因此,您将拥有以下格式的s4:
0000 abcd 0000 efgh 0000 ijkl 0000 mnop // s4
其中abcd , efgh , ijkl和mnop是每个字节加p到w的结果。
现在,请注意,您获得了x分布在4个字节中的位数的总和 。
( 总和,我想这就是变量中的s代表的总和)
0000 abcd //byte 1, left most, MSB
0000 efgh //byte 2, second from left
0000 ijkl //byte 3, second from right
0000 mnop //byte 4, rightmost, LSB
因此,您需要将结果合并到s4中的这四个字节中,以找到一个字节中的总和
(我想这就是s1的意思: sum in a byte )
您通过以下方式获得s1:
因此,发生以下操作(在位级别):
0000 abcd 0000 efgh 0000 ijkl 0000 mnop // s4
0000 0000 0000 0000 0000 0000 1111 1111 //m1
--------------------------------------- &
0000 0000 0000 0000 0000 0000 0000 mnop
0000 0000 0000 abcd 0000 efgh 0000 ijkl // s4 >> 8
0000 0000 0000 0000 0000 0000 1111 1111 //m1
--------------------------------------- &
0000 0000 0000 0000 0000 0000 0000 ijkl
.
.
0000 0000 0000 0000 0000 0000 0000 abcd // s4 >> 24
0000 0000 0000 0000 0000 0000 1111 1111 //m1
--------------------------------------- &
0000 0000 0000 0000 0000 0000 0000 abcd
可以看出,您仅添加了以下四个元素:
0000 0000 0000 0000 0000 0000 0000 mnop //0 to 8
0000 0000 0000 0000 0000 0000 0000 ijkl //0 to 8
0000 0000 0000 0000 0000 0000 0000 efgh //0 to 8
0000 0000 0000 0000 0000 0000 0000 abcd //0 to 8
--------------------------------------- +
//Final result, s1
您可以简单地将四个数字相加,每个数字的取值范围为0到8。因此,它必须得出0到32的值(0表示全为0,32表示全为8),即位数。在变量x中为1。 因此该函数名为bitCount 。
函数就是这样工作的。
最后的注意:知道这一点,您甚至可以用0x0F(而不是0xFF)更改m1,结果仍然相同。
在此声明之后:
int s4 = (x&m4) + ((x>>1)&m4) + ((x>>2)&m4) + ((x>>3)&m4) + ((x>>4)&m4) + ((x>>5)&m4) + ((x>>6)&m4) + ((x>>7)&m4);
由于S4中有4个字节,因此它的1个字节在x的相应字节中将具有1的数目。因此,显然,s4的每个字节在x的相应字节中均具有1的数目。
然后在语句中:int s1 =(s4&m1)+((s4 >> 8)&m1)+((s4 >> 16)&m1)+((s4 >> 24)&m1);
现在s4的1个字节在x的相应字节中将具有1的数目,然后将s4右移至8位将在x的字节2中给出2的数目,以此类推,这将是4个字节。 然后将所有数相加得到x的1的数目。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.