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作者对于位运算的使用已经达到了出神入化的境界了。