int lowbit(x){
return x & -x;
}
上述代码意思是x原码(二进制表示)的最后一个1所代表的实际数值。
比方说 lowbit(6) = 4
因为 6 可表示为 00…0110
而在二进制中‘~’就是把原码给倒过来(取反), 1变0 , 0变1。
就像 原码为 12, 补码就是 1100, ~12就是 0011。
根据平常学的数学,知道一个数加它的相反数,和为0。
但是 0011 + 1100 = 1111
实际是 12 + (-12) = 0;
而补码的含义是当其为非负数时,不变,同原码,为负数时,变为相反数 + 1。
那为什么是相反数+1呢
例如 7 - 3
补码处理后(仅供示例)变为了7 + (-3)
如果说单纯 7 + (~3)
则为 0111 + 1100 成了0011 (与溢出和进位有关,自行搜索)
但实际却7 + (-3) = 4
4 = 0100 对比0011
发现一式等于二式 + 1。
由此得知, 3补码应该等于 ~3 + 1;
因为这样恰好是4了。
如果不信,可以再举个例子,就是前面的12 + (-12)= 0
12原码为01100, ~12(反码)为 10011
相加得到的应该是0,却得了11111
但若是-12的原码等于~12 + 1的话,
那不就是0了吗?
所以说,负数x的补码等于-x + 1
即为~(-x) + 1
而正数n: ~n + 1= -n
而如开头代码所写 x&(-x)就等于 x&(~x + 1)
例如,当x = 5时 x&(~x + 1) 为 1
当x = 6时, 为2
那如何证明这是个对的算法呢?
一个数的二进制形式最后面的一个1后面一定没有1了。(废话)
那么他的补码绝对会把其最后一个1又转出来
例如 3 & (-3) 0011 & (1100 + 1)= 1
6 &(-6) 0110 & (1001 + 1)= 2
由此我们就验证了lowbit函数的这种写法。