java位运算

日常开发中位运算不是很常用,但是巧妙的使用位运算可以大量减少运行开销,优化算法。在看jdk源码时,很多地方用到位运算。
位移操作:(只针对 int类型的数据有效,java中,一个int的长度始终是32位,也就是4个字节,它操作的都是该整数的二进制数).也可作用于以下类型,即 byte,short,char,long(它们都是整数形式)。当为这四种类型时,JVM先把它们转换成int型再进行操作。

按位与(&)

按位与的运算规则

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

规则总结:只有两个操作数对应位同为1时,结果为1,其余全为0. (或者是只要有一个操作数为0,结果就为0)。

按位或(|)

按位或的运算规则

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

规则总结:只有两个操作数对应位同为0时,结果为0,其余全为1.(或者是只要有一个操作数为1,结果就为1)。

按位非(~)

按位非的运算规则

  • 把-5转位16位的二进制机器数:11111111 11111111 11111111 11111011

  • ~(-5) 取反结果:00000000 00000000 00000000 00000100

  • 转为十进制,结果为4

规则总结:~ 按位取反操作符,对每个二进制位的内容求反,即1变成0,0变成1。

按位异或(^)

按位异或的运算规则

  • 1^1=0
  • 1^0=1
  • 0^1=1
  • 0^0=0

规则总结:^ 异或操作符,相同位值为0 否则为1。

左位移(<<)

m << n的含义:把整数m表示的二进制数左移n位,高位移出n位都舍弃,低位补0. (此时将会出现正数变成负数的可能),如下实例:

5<<2 :把十进制的数值5左移两位,按如下步骤计算

  • 把5转位16位的二进制机器数:00000000 00000000 00000000 00000101
  • 按左移原理,将二进制数左移两位:00000000 00000000 00000000 00010100
  • 左移后结果为20

5<<29:把十进制的数值5左移29位,按如下步骤计算

  • 把5转位16位的二进制机器数:00000000 00000000 00000000 00000101
  • 按左移原理,将二进制数左移29位:10100000 00000000 00000000 00000000
  • 左移后高位是1,结果显然是负数

小结:m << n即在数字没有溢出的前提下,对于正数和负数,左移n位都相当于m乘以2的n次方。

右位移(>>)

m >>n 的含义:把整数m表示的二进制数右移n位,m为正数,高位全部补0;m为负数,高位全部补1(注意:这里计算是使用补码计算,计算机保存也是保存的补码),实例如下:

5>>2 :把十进制的数值5右移两位,按如下步骤计算

  • 把5转位16位的二进制机器数:00000000 00000000 00000000 00000101
  • 按右移原理,将二进制数左移两位:00000000 00000000 00000000 00000001
  • 右移后结果为1

-5>>2:把十进制的数值-5右移两位,按如下步骤计算

  • 把-5转位16位的二进制机器数(补码):11111111 11111111 11111111 11111011
  • 按右移原理,将二进制数右移两位:11111111 11111111 11111111 11111110
  • 右移后结果为-2

小结: m>>n即相当于m除以2的n次方,得到的为整数时,即为结果。

无符号右移(>>>)

m>>>n:整数m表示的二进制右移n位,不论正负数,高位都补0,实例如下:

-5>>>2:把十进制的数值-5右移两位,按如下步骤计算

  • 把-5转位16位的二进制机器数:11111111 11111111 11111111 11111011
  • 按右移原理,将二进制数右移两位:00111111 11111111 11111111 11111110
  • 右移后结果为正数
常见使用
  • m*2^n

可以使用m<< n求得结果,如:

System.out.println("2^3=" + (1<<3));//2^3=8
System.out.println("3*2^3=" + (3<<3));//3*2^3=24

计算结果是不是很正确呢?如果非要说2<<-1为什么不等于0.5,前面说过,位运算的操作数只能是整型和字符型。

  • 位移法则

    可以发现左移31位和-1位所得的结果是一样的,同理,左移30位和左移-2所得的结果也是一样的。移动一个负数位,是不是等同于右移该负数的绝对值位呢?输出一下就能发现不是的。java中int所能表示的最大数值是31位,加上符号位共32位。在这里可以有这样的位移法则:

    1、法则一:任何数左移(右移)32的倍数位等于该数本身。
    2、在位移运算m << n的计算中,若n为正数,则实际移动的位数为n%32,若n为负数,则实际移动的位数为(32+n%32),右移,同理。
    所以,左移是乘以2的幂,对应着右移则是除以2的幂。

不用临时变量交换两个数

这里写图片描述
上面的计算主要遵循了一个计算公式:b^(a^b)=a。

其实java中的异或运算法则完全遵守数学中的计算法则:

① a ^ a =0

② a ^ b =b ^ a

③ a ^b ^ c = a ^ (b ^ c) = (a ^ b) ^ c;

④ d = a ^b ^ c 可以推出 a = d ^ b ^ c.

⑤ a ^ b ^a = b.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值