1 java支持的位运算符:

&:按位与。

|:按位或。

~:按位非。

^:按位异或。

<<:左位移运算符。

>>:右位移运算符。

<<<:无符号右移运算符。

位运 算 符 中 ,除 ~ 以 外 ,其余 均 为 二 元 运 算 符 。 操 作 数 只 能 为 整 型 和字 符 型 数 据

 

 2.按位与(&)

操作数相同:

 

 

操作数不同:

 

 

 

 

 解析:将10进制的操作数数转成2进制数,再对两个二进制数进行与操作,结果为4

总结:只有两个(转成2进制数后)操作数对应位同为1时,结果为1,其余为0. (或者是只要有一个操作数为0,结果就为0)。然后再将得到的2进制数转成10进制

 

3 按位或(|),符号位不变

 操作数不同:

 解析:将10进制的操作数数转成2进制数,再对两个二进制数进行与操作,结果为7

 操作数相同:

 

 

 

总结:只有两个(转成2进制数后)操作数对应位同为0时,结果为0,其余全为1.(或者是只要有一个操作数为1,结果就为1)。然后再将得到的2进制数转成10进制

4按位非(~)

 

  解析:将10进制的操作数数转成2进制数,再对两个二进制数进行与操作,结果为-5(注意符号位也进行非运算)

总结:值为0时,结果为1;值为1时,结果为0

5 按位异或(^)

操作数相同时:

 

 操作数不同时:

 

 

总结:操作数相同时,结果为0,操作数不同时,结果为1 

6 左位移(<<)

符号位不变,低位补0。如:2<<2结果为8

 

 可以这样计算3<<2 = 3x22

 

7 右位移(>>)

低位溢出,符号位不变,并用符号位补溢出的高位。如:-6>>2结果为-2。

 

  可以这样计算10>>2= 10x2-2,

 并忽略小数取整

 

8 无符号右移(>>>)

低位溢出,高位补0

注意,无符号右移(>>>)中的符号位(最高位)也跟着变,无符号的意思是将符号位当作数字位看待。如:-1>>>1结果为2147483647。这个数字应该比较熟悉,看两个输出语句就知道是什么了:

-1>>>1竟然得到了int所能表示的最大整数,精彩。

 

使用位运算往往能很巧妙的实现某些算法完成一些复杂的功能。

这里我们举个例子:

在Integer类中有一个方法highestOneBit(int i),可以给它传入一个数字,它将返回小于等于这个数字的一个2的幂次方数。

这个方法的实现如下:

 

 它的思路就是:给定一个数字,通过一系列的运算,得到一个小于或等于该数字的一个2的幂次方数

其实这个过程可以抽象成这样:
现在有一个二进制数据,0001****,我们不关心低位的取值情况,我们对其进行右移并且进行或运算。

先将0001****右移1位,
得到00001***,再与自身进行或运算:
得到00011***

再将00011***右移2位,
得到0000011*,再与自身进行或运算:
得到0001111*

再将0001111*右移4位,
得到00000001,再与自身进行或运算:
得到00011111

再将得到的00011111无符号右移1位,得到00001111

将00011111-00001111=00010000,这个就是最终结果


右移与或运算的目的就是想让某个数字的低位都变为1,再用该结果 减去 该结果右移一位后的结果,则相当于清零了原数字的低位。即得到了我们想要的结果。

到此,只能感叹JDK作者对于位运算的使用已经达到了出神入化的境界了。

 

posted on 2020-04-12 19:36  路仁甲  阅读(537)  评论(0编辑  收藏  举报