在讲解之前,我们先回顾下二进制的原码、反码、补码之间的相互转换。
1、正数的二进制原码、反码、补码都是相同的,直接转换为二进制即可。
比如十进制数20, 转换为二进制数:20(10)=0001 0100(2),那么20的原码、反码、补码都是 0001 0100
2、负数的二进制原码:负数的绝对值的二进制的最高位变为1(1是标志位,只用来表示正负,1表示负数,0表示是正数。所以八位二进制的取值范围是[-127,127]),其余位与正数原码相同。
比如-20
第一步:20(10)=0001 0100(2)
第二步:最高位变为1:1001 0100
3、负数的反码:等于原码的最高位不变,其余取反。
比如-20
原码为:1001 0100
反码为:1110 1011
4、负数的补码:等于原码的最高位不变,其余取反,然后加一。
比如-20
第一步,原码为:1001 0100
第二步,最高位不变取反:1110 1011
第三步,加一得补码:1110 1100
5、已知一个数的补码,求原码的操作分两种情况:
(1)如果补码的符号位为“0”,表示是一个正数,所以补码就是该数的原码。
(2)如果补码的符号位为“1”,表示是一个负数,求原码的操作可以是:符号位为1,其余各位取反,然后再整个数加1,其实就是算负数补码的补码。
例如,已知一个补码为11111001,则原码是10000111(-7):因为符号位为“1”,表示是一个负数,所以该位不变,仍为 “1”;其余7位1111001取反后为0000110;再加1,所以是10000111。
现在进入正题,讲讲Java中的 << 、 >> 、>>>移位运算符的使用
1、<< 表示左移运算符,不分正负数,低位补0,num << 1,相当于num乘以2
注:以下数据类型默认为byte-8位
左移时不管正负,低位补0
正数:r = 20 << 2
20的二进制补码:0001 0100
向左移动两位后:0101 0000
结果:r = 80
负数:r = -20 << 2
-20 的二进制原码 :1001 0100
-20 的二进制反码 :1110 1011
-20 的二进制补码 :1110 1100
左移两位后的补码:1011 0000
反码:1010 1111
原码:1101 0000
结果:r = -80
2、>> 表示右移运算符,num >> 1,相当于num除以2,如果该数为正,则高位补0,若为负数,则高位补1;
注:以下数据类型默认为byte-8位
正数:r = 20 >> 2
20的二进制补码:0001 0100
向右移动两位后:0000 0101
结果:r = 5
负数:r = -20 >> 2
-20 的二进制原码 :1001 0100
-20 的二进制反码 :1110 1011
-20 的二进制补码 :1110 1100
右移两位后的补码:1111 1011
反码:1000 0100
原码:1000 0101
结果:r = -5
3、>>>表示无符号右移运算符,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0
正数: r = 20 >>> 2
的结果与 r = 20 >> 2 相同;
负数: r = -20 >>> 2
注:以下数据类型默认为int 32位
-20:源码:10000000 00000000 00000000 00010100
反码:11111111 11111111 11111111 11101011
补码:11111111 11111111 11111111 11101100
右移:00111111 11111111 11111111 11111011
结果:r = 1073741819