位运算技巧总结

        今天在Matrix67大牛的博客上看到了很多位运算的优化技巧,顿感位运算的神奇,现在来我总结一下位运算的神奇用法。

         下面是常见的位运算:

         

    a & b   a和b都是1的位取1,其他都取0。和&&有区别,&&是逻辑运算,返回true或者false
    a  |  b   a和b都是0的位取0,其余情况都取1。和||有区别,||是逻辑运算,返回true或者false
    a  ^ b   a和b相同的位取0,不同的位取1.
    ~a   a按位取反 一个无符号整形取反等于表示上限减去这个数, 比如12 假设是16位无符号整型,~12就是65535-12=65523
    a << b  a左移b位
    a >> b  a右移b位 

       

        下面是位运算的几种常见的用法:

       

    把a的末k位变成1           00110001 k=3 => 0110111      a | (1<<k - 1)
    把a的末k位取反         00110001 k=3 => 0110110      a ^ (1<<k -1)
    把a右边连续的1变成0      00110111 => 00110000    (a +1)&a
    把右边连续的0变成1        00101111 => 00100000    (a - 1)^a
    取右边连续的1                00101111 =>  1111            ((a+1) | a) >> 1
    去掉右起第一个1的左边   00101000 =>  x & (-x) 或者 x & (x ^ (x-1)) 这个在树状数组中会用到


        上面这些只是位运算的简单应用(已经非常强大了),还有一些更加强大的用处,第一个例子是,求一个32bit整数,求它的1的位数,代码如下:

       

    x := (x and $55555555) + ((x shr 1) and $55555555); 
    x := (x and $33333333) + ((x shr 2) and $33333333); 
    x := (x and $0F0F0F0F) + ((x shr 4) and $0F0F0F0F); 
    x := (x and $00FF00FF) + ((x shr 8) and $00FF00FF); 
    x := (x and $0000FFFF) + ((x shr 16) and $0000FFFF); 

 

        想一下怎么回事,比如x为21, 二进制为10101,把这个数代入代码中看下,

        第一步 : 10101 & 0101010101010101 + (1010)&0101010101  = 10101

        第二步 :10101&001100110011 + (101)&001100110011 = 10001+1 = 10010

        第三步:   10010&00001111 + 1&00001111 = 10+1= 11

        第四步:   11&11111111 + 0 = 11

        第五步:    11& 11111111 + 0 = 11
        

        上面五步得到了最终结果,答案为3,到这里,看出什么了吗?这段代码其实是用了分治的思想,我看了好久,这几个数字比较令人眼花。 下面让我来解释一下。比如这样一个数字,x32x31x30...x4x3x2x1 ,  第一步之后,变成了   x32x31两位表示x32和x31的和,x30x29表示x30和x29的和...以此类推。第二步之后,x32x31x30x29四位数字表示x32~x29的和,x28x27x26x25表示x28~x25四位数字的和,以此类推。第五步结束后x32~x1表示x32~x1这32位数字的和。如果你还是不清楚,请看下面这个图:

 

        如何只用位运算来求一个整数的绝对值呢? 一个正整数x和它的相反数-x的关系是,-x是x的补码,即-x=(~x)+1.x的绝对值代码为 x ^ (~(x >> 31) + 1) + x >> 31,当x为正数时,x>>31为0,取反变成-1,再加1变成0,0异或任何数不变;当x为负数时候,x>>31=1,1取反后加一变成0xFFFFFFFF,异或x之后,x每位取反,取反后再加一刚好是相反数。

       


          先写到这里,用到了再加

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值