位运算

本文详细解析了如何通过补码计算负数的绝对值和正数的相反数,包括补码的本质、负数绝对值的计算公式、正数相反数的计算方法以及相关数学证明。

1.绝对值

给出两种算法

a).n < 0时,~(n - 1);n >= 0 时,等于本身。

b).(n ^ (n >> 31)) - (n >> 31) ,设一个 int 为 32 位。

解释如下:

a).由于负数的补码等于除符号位之外的所有位取反后再加1,由于计算机内存中参与运算的负数都是补码形式,因此,为了求负数 n 的绝对值,需要先减1,再按位取反刚好是负数的绝对值(符号位1刚好也取反,变成0,表示正数,因此刚好是所求)。

b).

首先. n < 0时,设 n 的补码是 N,在计算机内存里原式为 (N ^ (N >> 31) - (N >> 31)) ,N >> 31 等于 -1,因为 >> 是带符号的位移,即移位时,符号位一直不变。而 -1 的补码是 2 ^ 31 - 1 = 0xFFFF,所以 N ^ ( -1 ) 相当于按位取反。后面的减负 1 即是加1.所以,当 n < 0 时,n 的绝对值为 ~(n) + 1。

与 a) 式联立有 :~(N - 1) = ~(N) + 1,那么,这个式子是不是成立的呢?

证明:不论 N 是否小于 0,总有 ~(N - 1) = ~(N) + 1。

证:

由于 ~(x) + x = ~(0)对于所有 x 是成立的,因此 ~(x) = ~(0) - x,~(x - 1) = ~(0) - x + 1,故 ~(N - 1) = ~(0) - N + 1 = (~(0) - N) + 1 = ~(N) + 1

即原式得证

故一个负数 n 的绝对值是 ~(n) + 1 是正确的

再者. n >= 0 时,n >> 31 为 0,所以上式的结果还是 n。一个正数的绝对值是本身,是正确的。

因此,b) 命题得证。


2.补码本质

想像一个钟表有 N 格,上面每格依次标记为 0 ~ N - 1,顺时间方向走 x 格,等价于逆时钟走 N - x 格。即 x 的补码是 N - x。

可参照我的另一篇文章《补码的实质》


3.判断 n 是不是2的幂

0 == n & (n - 1)


4.相反数

我们在第一个命题中已经证明 :当 n < 0 时,n 的绝对值为 ~(n) + 1,也即 n < 0 时,n 的相反数是 ~(n) + 1;

当 n > 0 时,求其相反数就是求 - n 的补码,要把 -n 的各位除符号位外取反,再加 1,也即 ~(-n除符号位外) + 1,而此式刚好就等于 ~(n) + 1,刚好把符号位变为 1,所以刚好是所求。

n 的相反数是 ~(n) + 1


5.最大值,最小值

max(a,b) = a & ((b - a) >> 31) | (b & (~(b - a)) >> 31) //注意 | 后面的一项不能写为 b & ((a - b) >> 31),考虑到 a == b 的情况,这样写是错误的。

min(a, b) = a & ((a - b) >> 31) | (b & (~(a - b)) >> 31)


或者 

min(a,b) = a ^ ((a ^ b)  & -(a < b)) 

解释:当 b >= a 时,-(a - b) 为 0 ,整个结果为 a;当 a > b 时,-(a < b) 为 -1 ,任何数与 -1 相与结果不变,所以,整个结果为 a ^ a ^ b 为 b.


6. n & (n - 1) 令 n 中的 1 减少一个

如二进制 1010,进行运算 1010 & (1010 - 1) = 1 000,原来的二进制数中有两个 1,现在只有一个 1了。

证明:

设 

N - 1 可以理解为 N 的最低位的一个 1 拿来减 1,那么这个位前面所有的位都保持不变,设最后一个 1 位为第 m 位,设这个位前面所有位构成的数字为 M,则

作图 1 并给出证明如下:


图 1 n & (n-1) 比 n 少一个 1

有了这个结论之后,就可以用来计算一个整数中,有多少个 1.给出代码如下:

int count1(int n)
{
    int ncount = 0;
    for(; n ;++ ncount)
    {
        n &= (n - 1);//每次都减少一个1,直到 n 中没有1
    }
    return ncount;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值