前言:
最近刚开始看《码出高效-Java开发手册》,看到位移运算这里发现了一个以前没有关注过的点,也就是博客标题,百思不解,经过一番搜索才真的了解了位移运算的实质。
我们知道位移符号一共有三种,左移<<、右移>>、无符号右移>>>
左移<<和右移>>
在左移<<和右移>>两种运算中,符号位均参与移动,除负数往右移动,高位补1之外,其他情况均在空位补0。
无符号右移>>>
当向右移动时,正负数高位均补0,正数不断向右移动的最小值是0,而负数不断向右移动的最小值是1。无符号意即藐视符号位,符号位失去特权,必须像其他平常的数字位一起向右移动,高位直接补0,根本不关心是正数还是负数。
先上代码看看:
public static void main(String[] args) { int num = -32,num1 = -64,num2 = 32; int a = num >> 33; int b = num >>> 31; int c = num1 >>> 64; int d = num1 >>> 63; int h = num1 >>> 65; int e = num2 >> 33; int f = num2 >>> 31; System.out.println("-32 >> 33:" + a); System.out.println("-32 >>> 31:" + b); System.out.println("-64 >>> 64:" + c); System.out.println("-64 >>> 63:" + d); System.out.println("-64 >>> 65:" + h); System.out.println("32 >>> 33:" + e); System.out.println("32 >>>> 31:" + f);
运算结果:
这里我们可以重点看一下-64的无符号右移
第一个问题:-64 >>> 64的结果是-64,不是说负数不断地无符号向右移动的最小值是1吗?
第二个问题:-64 >>> 63的结果是1,按照上面的说法似乎没有疑问,但是为什么呢???
第三个问题:-64 >>> 65的结果为什么那么大?
在实际编程中,位移运算仅作用于整型(32位)和长整型(64位)数上,假如在整型数上移动的位数是字长(同一时间处理二进制的位数)的整数倍,无论是否带符号以及移动方向,均为本身(这里解决了第一个问题)。
因为移动的位数是一个mod64的结果,即:对一个64位数进行无符号右移操作时,实际的位移为 位移值%64 也就是 >>>64 = >>>0,那么,一个64位数一次最大无符号右移值为63位,由于负数的第一位为-1,则-1XXX(63位X)>>>63 = 000(63个0)1。(这里解决了第二个问题)
而对于32位的数再说,无符号右移位数为 位移值%32 ,像short这种类型的数,在做位移之前,会先转为int类型,然后再进行转换。
那么,第三个问题的答案自行思考吧
这里还是举例补充说明一下吧,毕竟我也理解了很久
System.out.println("-16无符号右移2位:"+(-16>>>2)); //-16无符号右移2位:1073741820
这个是为什么?
首先一定要知道 无符号右移运算符>>> 只是对32位和64位的值有意义,这个在前面也说了
例如: -16的无符号右移2位应该这样算才对----------------------取32位长度的16的二进制补码加1
16二进制:00000000 00000000 00000000 00010000
补码+1后:11111111 11111111 11111111 11110000
右移两位高位补零:00111111 11111111 11111111 11111100
这个二进制对应的值就是1073741820