java移位符初步使用与简单理解
java移位符初步使用与简单理解
概述
java移位符主要包括3种:
运算符 | 名称 |
---|---|
>> | 左移运算符 |
<< | 有符号右移运算符 |
<<< | 无符号右移运算符 |
这里我们先附上代码运行实例,原理将在后面以解析下面代码的方式进行讲解:
public class BitOperatorTest {
public static void main(String[] args){
System.out.println(1 << 4);
System.out.println(-1 << 3);
System.out.println(8 >> 3);
System.out.println(-8 >> 3);
System.out.println(-8 >>> 3);
}
}
结果如下:
16
-8
1
-1
536870911
首先我们需要清楚在计算机系统中,数值一般用补码来表示,主要原因是因为使用补码可以使符号位和其他位统一处理,我们需要将上面的数值都转化为补码。
左移运算符
1 << 4
首先我们将1化为源码:0000 0000 0000 0000 0000 0000 0000 0001 (因为其是int类型,所以化为二进制有32位)
正数的补码和反码等于源码的本身。所以补码也为上述二进制代码。
左移运算符是将操作数的二进制码整理左移指定位数,左移后右面空出的位用0来补充。
左移4位 0000 0000 0000 0000 0000 0000 0000 0001 1*2^0=1
0000 0000 0000 0000 0000 0000 0000 0001 0000 (红色被移除截断,蓝色是新补的0) 1*2^4=16
-1 << 3
我们开始第二个输出语句,这是一个负数。负数的反码是他的源码符号位不变,其余按位取反。补码是他的反码加一。
所以我们可以得到-1的源码为1000 0000 0000 0000 0000 0000 0000 0001 -1*2^0=-1
反码为1111 1111 1111 1111 1111 1111 1111 1110
补码为1111 1111 1111 1111 1111 1111 1111 1111
对补码进行操作得111 1111 1111 1111 1111 1111 1111 1111 1000 (红色被移除截断,蓝色是新补的0)
将结果数转化为源码得1000 0000 0000 0000 0000 0000 0000 1000 -1*2^3=-8
总结
所以通过上面对左移运算符的简单使用不难发现,我们可以将其简便理解为移动几位,就是为操作数乘以2的几次方。
右移运算符
左移运算符不牵扯符号位的增补符号位,所以没有有无符号分类
有符号右移运算符
8 >> 3
根据上面流程,我这里直接就简化为
源码为:0000 0000 0000 0000 0000 0000 0000 1000 1*2^3=8
反码为:0000 0000 0000 0000 0000 0000 0000 1000
补码为:0000 0000 0000 0000 0000 0000 0000 1000
运算后结果:0000 0000 0000 0000 0000 0000 0000 0001 000 1*2^0=1(红色被移除截断,蓝色是新补的符号位,并且以原来的符号位填补)
-8 >> 3
根据上面流程,我这里直接就简化为
源码为:1000 0000 0000 0000 0000 0000 0000 1000 -1*2^3=8
反码为:1111 1111 1111 1111 1111 1111 1111 0111
补码为:1111 1111 1111 1111 1111 1111 1111 1000
运算后结果:1111 1111 1111 1111 1111 1111 1111 1111 000 (红色被移除截断,蓝色是新补的符号位,并且以原来的符号位填补)
转换为源码为:1000 0000 0000 0000 0000 0000 0000 0001 -1*2^0=-1
总结
同左移运算符一样,总结规律后可得出,右移运算符移动几位则是对操作数除以2的多少次方。
无符号右移运算符
-8 >>> 3
根据上面流程,我这里直接就简化为
源码为:1000 0000 0000 0000 0000 0000 0000 1000 -1*2^3=8
反码为:1111 1111 1111 1111 1111 1111 1111 0111
补码为:1111 1111 1111 1111 1111 1111 1111 1000
运算后结果:0001 1111 1111 1111 1111 1111 1111 1111 000 (红色被移除截断,注意黄色部分,在无符号右移运算位中统一补0)
此时数值将会非常大,所以得到程序中的结果。
补充
如果操作类型低于int类型,比如byte,char等,先将其转化为int类型在进行移位。
对于int类型的移位,如果移动位数超过32位,则让位数对32取余,然后进行运行,即a>>33 == a>>1 a>>32 ==a
同样如果对于long类型的移位,移动位数超过64,则也需要对移动位数进行处理。
代码补充
对于补充内容的代码不进行详解,代码及运算结果如下,基本流程与上面类似,
代码:
public class BitOperatorTest {
public static void main(String[] args){
System.out.println((char)4 << 4);
System.out.println(4 << 4);
System.out.println(4 << 36);
System.out.println((long)1214 >> 66);
System.out.println((long)1214 >> 2);
}
}
运行结果:
64
64
64
303
303