位操作

位操作应该说从学C的时候就接触过,一开始以为没什么大用,但是现在在不断的学习和有了工作经验之后,发现这个东西真是个好东西,很多便捷操作都可以借助它来实现,并且很有效率。

参考文章:

位操作基础篇

《算法心得》参考的不多,里面很底层。

位操作基础
符号描述规则
&按位与两个位都是1,结果才是1(1&1=1;1&0=0)
|        按位或两个位都是0,结果才是0(1&0=1;0&0=0)
^按位异或两个位相同为0,相异为1(1&0=1;1&1=0)
~按位取反0变1,1变0(单目操作符,优先级高
<<左移左移若干位,丢弃高位,低位补0
>>右移右移若干位;无符号数,高位补0,有符号数,算数右移(补符号位)或者逻辑右移(补0)








1. 针对右移,需要简单扩展一下。

逻辑右移:不考虑符号位,右移一位,左边补0;

算术右移:考虑符号位,右移一位,若符号位为1,左边补1,否则补0。(可以进行有符号位的除法,右移n位=除2的n次方)。

8的二进制:1100 1101。

逻辑右移:[0]110 0110。

算术右移:[1]110 0110。

2. 符合操作符

&=、|=、^=、<<=、>>=。

常用位操作

1.判断奇偶

奇数偶数只要根据最后一位是1还是0就能判断出,传统的操作比如(i % 2 == 0)来判断,位操作里可以用&来代替。实际测试代码来看,确实时间花费要少许多。

        for(int i = 0; i < 101 ; i++){
            if( (i & 1) == 0){
                System.out.println(i);
            }
        }
2.交换2数

这个我在很早的面试宝典里就看见过了,心想,何必这么秀呢。

        if(a != b){

            a ^= b;
            b ^= a;
            a ^= b;

        }

异或运算法则如下:

1. a ^ b = b ^ a;

2. a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c;

3. a ^ b ^ a = a ^ a ^ b = 0 ^ b = b(a和自己异或等于0,0和任意数异或还等于自己);

通过以上三个法则就能来推到两数交换了,很简单其实。

3.变换符号

这个其实没什么说头,就是当初学习正数负数的二进制操作时所说的取反+1操作的代码实现。

~a + 1
4.求绝对值

主要看当前的数是正数还是负数来决定,能决定的就是符号位,因此先右移得到,高1位,然后判断是0还是1,再做取反+1操作即可。

        int i = a >> 31;
        return (i == 0) ? a : ~a + 1;

但是比较苛刻的用法此处还能优化,,比如在第一点里的异或规则我们知道,a ^ 0 = a ,而 a ^ -1 = ~a(任何数和-1异或相当于取反操作,因为-1的二进制码是1111 1111,很特殊)。

加上我们i的取值在a右移31位后刚好是0或者-1,所以可以写成下面这种。

        int i = a >> 31;
        return ((a ^ i) - i);
        //i 为0时 return ((a ^ 0)-0);
        //i 为-1时 return ((a ^ -1) - (-1)) == (~a + 1);
5判断一个数是不是2的幂

我们发现2的幂的数的二进制都是最高位是1,其余都是0,那么如何判断这种呢?可以将高位1变成0,其余变成1,按位与操作,这样,如果还是0,说明是2的幂,如果不是0,说明不是。

  return i & (i-1) && (i != 0);
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值