为什么n按位和-n总是返回最右边的位(最后一位)

时间:2019-01-26 02:52:38

标签: algorithm bit-manipulation

这是python代码段:

1 & -1 # 1
2 & -2 # 2
3 & -3 # 1
...

似乎任何n & -n总是返回最右(最后)一位,我真的不知道为什么。有人可以帮助我了解这一点吗?

4 个答案:

答案 0 :(得分:1)

〜x = -1 -x

如此

-x =〜x + 1

取x(〜x)的补码时,所有0位变为1,而所有1位变为0。例如101100->010011。

当您添加1时,右侧的连续1会变为0,并且第一个0位会被设置为1:010011-> 010100

如果与原始文件相同,则顶部的0位变为1。通过加法将底部的1位翻转为0,只有最右边的1位变为补码中最右边的0位,加法后被重置为1,两边均为1:101100&010100-> 000100

答案 1 :(得分:1)

这是由于负数以二进制表示的方式,称为二进制补码。

创建数字n的二进制补码(换句话说,创建-n的表示形式):

  • 反转所有位
  • 加1

因此,换句话说,当您写1 & -1时,它的意思是1 & ((~1)+1)。开头的~1给出值1111110,加一个得出11111111。 (在这些示例中,我们坚持使用8位。)将值与1进行“与”运算得到1

在下一种情况下,2 & -2表示2 & ((~2)+1)。将2取反,得到11111101,加1得到11111110。然后,与2(二进制文件10进行AND运算得到2

最后,3 & -3的意思是3 & ((~3)+1)。取反3得到11111100,加1得到11111101,然后与3(二进制11进行AND)得到1。 / p>

答案 2 :(得分:0)

整数以二进制形式存储在内存中。非负整数按原样存储在二进制中,但负数以二进制补码形式存储。例如,取任意数字158。

  

158 = 0000000010011110

而其否定的。

  

-158 = 1111111101100010

取任意数字并按位与负数相加,则将获得最右边的设置位。这是因为在二进制补码的转换过程中,我们从右开始,将位按原样放置,直到遇到第一个置位。那就是最右边的设置位被原样写入。然后,我们从此处开始向左翻转数字。 但是,上述过程只是计算2的补数的快捷方法。对于实际过程,您必须首先对数字取1的补码(将所有未设置的位翻转为未设置,未设置的所有位翻转为未设置),然后将1加到整个结果中。现在,您可以了解为什么此快捷方式每次都有效 Why does this two's complement shortcut work?

这将为您提供更多的见解https://www.geeksforgeeks.org/efficient-method-2s-complement-binary-string/

拿一些数字并做例子,看看自己。

答案 3 :(得分:0)

难点在于计算2的补码而不是执行按位AND运算,并且AND始终需要相同的东西才能使它成为真。

2的补码的作用是,使两个数字的最右边的数字参与按位AND运算,查看下面如何计算2的补码运算,您会发现我们用二进制和十进制表示数字(十进制)然后要计算2的补码,我们从右开始,将所有二进制数字复制相同,直到看到第一个1,然后当看到第一个1时,将所有左数都设为与前一个相反。

收获是:

假设您想要2的4的补数,即(-4),所以它表示的是二进制的十进制数,并从右开始复制所有位(0)直到看到第一个1,然后反转所有0和1。

示例:我们想要2的补数 6-> 0 1 1 0 = 0 0 1 0 ,从0110的右边开始,直到我们看到第一个1,我们才精确复制第一个中的内容然后我们将所有的0和1反转。

另一个带有2的补码的操作

0 100

1 100 (粗体字与上面相同)

  

现在很明显,当按位进行 AND 时,最右边的   只能通过 AND 操作完成数字操作   等于通过 AND