算法通关村——位运算的常用技巧

首先我们先简单的了解一下位运算,众所周知,我们的数据是以二进制的形式储存在我们的计算机中的。位运算是计算机的核心基础,数据的表示和计算几乎都少不了,在JVM以及很多高性能代码里大量使用,甚至很多算法本身就是基于位进行的。在算法方面,很多位相关的算法有很多技巧,不学真不知道。另外很多算法虽然看起来与位运算无关,但是用位操作优化一下,性能会提升很多,所以位运算的问题值得好好学习。

与、或、异或和取反

与的运算符是&,运算规则是: 对于每个二进制位,当两个数对应的位都为 1 时,结果才为 1,否则结果为 0。

  • 0&0=0
  • 1&0=0
  • 0&1=0
  • 1&1=1

或的符号是|,运算规则是: 对于每个二进制位,当两个数对应的位都为 0 时,结果才为 0,否则结果为 1。

  • 0|0=0
  • 1|0=1
  • 0|1=1
  • 1|1=1

异或运算的符号⊕(在代码中用^表示异或),运算规则是: 对于每个二进制位,当两个数对应的位相同时,结果为 0,否则结果为 1。

  • 0⊕0=0
  • 1⊕0=1
  • 0⊕1=1
  • 1⊕1=0

取反运算的符号是~,运算规则是: 对一个数的每个二进制位进行取反操作,0 变成1,1 变成 0。

  • ~0=1
  • ~1=0

以下例子显示上述四种位运算符的运算结果,参与运算的数字都采用有符号的 8 位二进制表示46 的二进制表示是 00101110,51 的二进制表示是 00110011。考虑以下位运算的结果。。46&51的结果是34,对应的二进制表示是 00100010。
46|51 的结果是63,对应的二进制表示是 00111111。
。46田51的结果是29,对应的二进制表示是 00011101.
。~46 的结果是-47,对应的二进制表示是 11010001。
。~51 的结果是 -52,对应的二进制表示是 11001100。

位运算常用技巧

幂等律: a &a=a,a a=a (注意异或不满足幂等律) ;
交换律: a & b=b &a,al b=b a,a⊕b=b⊕a;
结合律: (a & b) & c=a &(b & c),(alb)  c=a(b c),(ab)⊕c=a⊕(b⊕c);分配律: (a&b)l c=(a c &(b c, (al b) & c=(& c)b &c,ab) & c=(a& cb &c);
德摩根律: ~(a & b)=(~a) l (~b),~(a | b)=(~a) & (~b);
取反运算性质: -1=~0,-a=~(a-1);
与运算性质: a & 0=0,a &(-1)=a,a & (~a)=0;
或运算性质: a =a;
异或运算性质: a⊕0=a,a⊕a=0;

获取某一位数的代码

boolean getBit(int num,int i){
    //检查该结果是否为零。不为零说第i位为1
    return (num&(1<<i)!=0);
}

设置某一位为1

int setBit(int num,int i){
    return num|(1<<i);
}

清零(将某一位设置为0)

int clearBit(int num,int i){
    int mask = ~(1<<i);
    return num&mask;
}

更新(将清零和设置结合起来)

int update(int num,int i ,int v){
    int mask = ~(1<<i);
    return (num&mask)|(v<<i);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值