为什么x&-x可以获取x的最低位的1?

Part 1

我们首先需要理解 − x = ∼ x + 1 -x=\sim x+1 x=∼x+1。众所周知,计算机是通过补码的方式存储整数的(关于补码的知识可以阅读CSAPP)。

我们先来感性认识一下:对于一个整数,例如6=0b0110,~ 6=0b1001,~6+1=0b1010=-6。接下来我们来严格证明一下:

x = − a w ∗ 2 w + ∑ i = 0 w − 1 a i ∗ 2 i − x = a w ∗ 2 w − ∑ i = 0 w − 1 a i ∗ 2 i ∼ x = − ( 1 − a w ) ∗ 2 w + ∑ i = 0 w − 1 ( 1 − a i ) ∗ 2 i ∼ x + 1 = − 2 w + a w ∗ 2 ∗ w + ∑ i = 0 w − 1 2 i − ∑ i = 0 w − 1 a i ∗ 2 i + 1 = − x □ x=-a_w*2^w+\sum_{i=0}^{w-1}a_i*2^i\\-x=a_w*2^w-\sum_{i=0}^{w-1}a_i*2^i\\\sim x=-(1-a_w)*2^w+\sum_{i=0}^{w-1}(1-a_i)*2^i\\\sim x+1=-2^w+a_w*2*w+\sum_{i=0}^{w-1}2^i-\sum_{i=0}^{w-1}a_i*2^i+1=-x\Box x=aw2w+i=0w1ai2ix=aw2wi=0w1ai2ix=(1aw)2w+i=0w1(1ai)2ix+1=2w+aw2w+i=0w12ii=0w1ai2i+1=x

Part 2

然后我们去理解 x & ( ∼ x + 1 ) x\&(\sim x+1) x&(x+1)就可以得到最低位的1。

∼ x \sim x x后,原本是0的位置都变成了1,原本是1的位置都变成了0,再次+1后,低位原本是0 的位置由于全部变成了1然后都会进位,直到进位到第一个原本是1的位置(此时是0)。也就是说原本最低位的1再次变成了1,而高位全部相反,低位全都是0,所以再次&后就会得到最低位的1。

Part 3

我们都知道,一个字长为w的整数,可以表示的范围是 2 w − 1 ∼ − 2 w 2^w-1\sim -2^w 2w12w,对于最小值MIN,我们是无法表示-MIN也就是 2 w 2^w 2w,在实际环境,计算机会进行 ∼ M I N + 1 \sim MIN+1 MIN+1的运算,最终得到MIN本身,也就是说,-MIN=MIN。

int main() {
    int x = INT_MIN;
    cout << x << endl;
    cout << -x << endl;
    if (x == -x) {
        cout << "same" << endl;
    } else {
        cout << "different" << endl;
    }
    return 0;
}
/*运行结果
-2147483648
-2147483648
same
*/

所以MIN&-MIN并不会得到最低位的1,而是会得到0。因此我们在使用x&-x得到x最低位1的时候必须特判x是否为MIN,否则会有潜在的BUG。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值