【编程小记】位运算 x & -x 表示含义

一、原码反码补码

在计算机中,整数的数据的存储是按照补码的方式进行存储的

按照数据与0的大小,数据又被分为正数与负数

  • 正数的原码反码补码相同。
  • 负数的原码,反码,补码并不相同。它们之间的转换关系如下:
    • 负数的反码:该负数的原码除符号位外各位取反。
    • 负数的补码:负数的反码 + 1

我们来看下面的一个例子理解原码反码补码的求解:

[+1] = [00000001]= [00000001]= [00000001][-1] = [10000001]= [11111110]= [11111111]

通过上面的例子我们可以知道:
在计算机中取一个数 x(可正可负)的相反数,其实也就等价于:这个数的补码的基础上进行按位取反(包括符号位)之后在增加1

即:-x = (~x) +1

二、位运算 x & -x 表示含义

下面我们来讨论: 位运算 x & -x 表示含义

x为奇数时

例如: x = 3

x = 3
// 00000000  00000000  00000000  00000011   补码
-x
// 11111111  11111111  11111111  11111101   补码
ret = x & -x
//00000000  00000000  00000000  00000011   补码
//11111111  11111111  11111111  11111101   补码
ret
//00000000  00000000  00000000  00000001   补码

可以看到对于一个奇数如果执行表达式ret = x & -x 那么得到的结果是1,如果你不相信,你还可以试一试其他奇数。

原理分析

对于一个奇数 x,其比特位最后一位(最右边的那一位)一定是1 ,对这个奇数x取相反数也就相当于按位取反然后加一,奇数按位取反以后最后一位一定是0,然后+1后最后一位一定是1,但是 -x 除了最后一位与 x 相同,其余均不同,于是x & -x的结果一定是 1。

举例:

[+1]//   00000001  奇数的最后一位一定是1

[-1]//   11111111  相反数是 按位取反 然后 +1, 导致最后一位与原数相等

x为偶数时

例如 x = 4

x = 6
// 00000000  00000000  00000000  00000110   补码
-x
// 11111111  11111111  11111111  11111001   反码
// 11111111  11111111  11111111  11111010   补码
ret = x & -x
// 00000000  00000000  00000000  00000110   补码
// 11111111  11111111  11111111  11111010   补码
ret
// 00000000  00000000  00000000  00000010   补码

观察结果ret我们会发现:

  1. 这个结果只有一位值是1, 其他位均是0 ,而且这个值为 1 的位置是与原数 x 从右向左第一个比特位为 1 的位置相同
  2. 这个值的末位0的个数与原值 x 保持一致

原理分析

  1. 原数 x 最低非0位右边所有的0,经由取反后全部变为1,反码+1会导致这些1逐位发生进位并变为0,最终进位记到最低非0位。
  2. 原最低非0位是1,取反后是0,进位到这一位0变成1,不再向左进位
  3. 原最低非0位左边的每一位经由取反后 和 原码 进行与运算必为0

三、最终结论

当一个数与其相反数相与(&):

如果这个数是奇数, 则结果必为1(这个1的位置与原数的最低非零位位置相同)。

如果这个数是偶数, 则结果是一个特殊的数据,与原数据的最低非零位相同位置为1,其他位置全为0

用途: 一般可以用来获取某个二进制数的最低非零位

猜你喜欢

转载自blog.csdn.net/qq_65207641/article/details/129927644
x