使用位运算求绝对值

今天看到有人说可以用位运算求绝对值,于是自己尝试推导了一下,然而没推出来。看了网上其他人的讲解,觉得这个问题很有意思,有必要记录一下。

在计算机基础课程里面我们知道,对于负数而言,原码转补码是 除符号位取反加1,补码转原码也是 除符号位取反加1。同时,如果我们求出了一个负数的原码,那么它的绝对值就很好求了,只需将这个原码的符号位取反即可(将1取反为0)。梳理一下,补码转原码时,除符号位都取反了,原码转绝对值时,符号位被取反了,那么,其实我们可以将这两次取反操作合在一起,即:对补码的所有位取反,然后加1,可得到该补码对应的负数的绝对值。

假设a是32位负整数,那么

  • a的符号位是1,(a >> 31) 是 111...111,一共32个1,也就是-1的补码
  • 和1进行异或 相当于 取反,即 0 ^ 1 = 1,1 ^ 1 = 0,
  • x + 1 相当于 x - (-1),x是任意数,

那么

  • 将a按位取反的算法是:a ^ (a >> 31),
  • 将a将位取反加1的算法是:(a ^ (a >> 31)) + 1 == (a ^ (a >> 31)) - (-1) == (a ^ (a >> 31)) - (a >> 31)。

对应的代码是:

int abs(int n) {
    int bits = sizeof(int) * 8 - 1;
    return (n ^ (n >> bits)) - (n >> bits);
}

其实这个算法同样适用于正整数求绝对值,因为,

假设b是32位正整数,那么

  • b的符号位是0,(b >> 31) 是 000...000,一共32个0,也就是0的补码
  • 和0进行异或 相当于 不变,即 0 ^ 0 = 0,1 ^ 0 = 1,

那么 

(b ^ (b >> 31)) - (b >> 31) == b。

 

 

  • 8
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值