(数字)&( – 数字)的含义

(number) & (-number)是什么意思? 我搜索了它,但无法找到意义

我想在i & (-i)循环中使用i & (-i)

 for (i = 0; i <= n; i += i & (-i)) 

假设2的补码(或者i是无符号的),- -i等于~i+1

i & (~i + 1)是提取i的最低设置位的技巧。

这是有效的,因为+1实际上做的是设置最低的清除位,并清除低于该值的所有位。 因此,在i~i+1设置的唯一位是来自i的最低设置位(即, ~i的最低清除位)。 低于该比特的比特在~i+1中是清楚的,并且高于该比特的比特在i~i之间是不相等的。

在循环中使用它看起来很奇怪,除非循环体修改i ,因为i = i & (-i)是幂等操作:执行两次会再次给出相同的结果。

[编辑:在其他地方的评论中,你指出代码实际上是i += i & (-i) 。 那么对非零i是清除i的最低设置位组,并将下一个清除位设置为高于该值,例如101100 – > 110000.对于没有高于最低设置位的清除位(包括i = 0 ),它将i设置为0.因此,如果不是因为i0开始,每个循环将i增加至少两倍于前一循环,有时更多,直到最终它超过n并打破或转到0并永远循环。

在没有注释的情况下编写这样的代码通常是不可原谅的,但是根据问题的领域,这可能是一个“明显的”循环值序列。

我想我只是花一点时间来展示它是如何工作的。 此代码为您提供最低设置位的值:

 int i = 0xFFFFFFFF; //Last byte is 1111(base 2), -1(base 10) int j = -i; //-(-1) == 1 int k = i&j; // 1111(2) = -1(10) // & 0001(2) = 1(10) // ------------------ // 0001(2) = 1(10). So the lowest set bit here is the 1's bit int i = 0x80; //Last 2 bytes are 1000 0000(base 2), 128(base 10) int j = -i; //-(128) == -128 int k = i&j; // ...0000 0000 1000 0000(2) = 128(10) // & ...1111 1111 1000 0000(2) = -128(10) // --------------------------- // 1000 0000(2) = 128(10). So the lowest set bit here is the 128's bit int i = 0xFFFFFFC0; //Last 2 bytes are 1100 0000(base 2), -64(base 10) int j = -i; //-(-64) == 64 int k = i&j; // 1100 0000(2) = -64(10) // & 0100 0000(2) = 64(10) // ------------------ // 0100 0000(2) = 64(10). So the lowest set bit here is the 64's bit 

它对无符号值的作用相同,结果始终是最低设置位的值。

鉴于你的循环:

 for(i=0;i<=n;i=i&(-i)) 

没有设置位( i=0 ),因此您将在此操作的增量步骤中返回0。 所以这个循环将永远继续,除非n=0i被修改。

假设负值使用二进制补码。 然后-number可以计算为(~number)+1 ,翻转位并加1。

例如,如果number = 92 。 然后这就是二进制文件中的样子:

 number 0000 0000 0000 0000 0000 0000 0101 1100 ~number 1111 1111 1111 1111 1111 1111 1010 0011 (~number) + 1 1111 1111 1111 1111 1111 1111 1010 0100 -number 1111 1111 1111 1111 1111 1111 1010 0100 (number) & (-number) 0000 0000 0000 0000 0000 0000 0000 0100 

从上面的例子可以看出(number) & (-number)给你的位数最少。

您可以在IDE One上看到代码在线运行: http : //ideone.com/WzpxSD

这是一些C代码:

 #include  #include  #include  using namespace std; void printIntBits(int num); void printExpression(char *text, int value); int main() { int number = 92; printExpression("number", number); printExpression("~number", ~number); printExpression("(~number) + 1", (~number) + 1); printExpression("-number", -number); printExpression("(number) & (-number)", (number) & (-number)); return 0; } void printExpression(char *text, int value) { printf("%-20s", text); printIntBits(value); printf("\n"); } void printIntBits(int num) { for(int i = 0; i < 8; i++) { int mask = (0xF0000000 >> (i * 4)); int portion = (num & mask) >> ((7 - i) * 4); cout << " " << std::bitset<4>(portion); } } 

这里还有一个C#.NET版本: https : //dotnetfiddle.net/ai7Eq6