位运算
位运算:在计算机中,所有的数都是以二进制进行存储。而位运算就是计算机对二进制数直接进行移位运算。
<<(左移操作符)
对数进行操作时,左移多出来的直接溢出,缺少的用0补上。
byte a = 2; //0000 0010
a <<= 2; //0000 1000
System.out.println(a); //8
byte b = -2; //1000 0010
b <<= 2; //1000 1000
System.out.println(b); //-8
byte c = 64; //0100 0000
c <<= 2; //0000 0000
System.out.println(c); //0
>>(右移操作符)
对数进行操作时,每移一次,最高位由原来的补充(正数补0,负数补1),多出来的溢出。
byte a = 8; //0000 1000
a >>= 2; //0000 0010
System.out.println(a); //2
byte b = -8; //1000 1000
b >>= 2; //1000 0010
System.out.println(b); //-2
byte c = 2; //0000 0010
c >>= 2; //0000 0000
System.out.println(c); //0
>>>(无符号右移操作符)
对数进行操作时,每一次移动,右移多出来的溢出,最高位补0
byte a = 8; //0000 1000
a >>>= 2; //0000 0010
System.out.println(a); //2
byte b = -8; //1000 1000
b >>>= 2; //1000 0010
System.out.println(b); //-2
byte c = 2; //0000 0010
c >>>= 2; //0000 0000
System.out.println(c); //0
注意事项
每个数在计算机中保存是以补码的形式保存,所以进行位运算时,也是移动其补码。
在此进行几个详细的例子说明(以>>为例)
byte a = 8; //0000 1000(原码)
//0000 1000(补码)
a >>= 2; //0000 0010(补码移位)
//0000 0010(移位后的原码)
System.out.println(a); //2
byte b = -8; //1000 1000(原码)
//1111 1000(补码)
b >>= 2; //1111 1110(补码移位)
//1000 0010(移位后的原码)
System.out.println(b); //-2
无符号右移的陷阱
byte a = -128;
a >>>= 2;
System.out.println(a);
a ?= -32
遇到这种情况后,是不是会怀疑前面的理论出现错误了呢?
其实并不是,而是这段代码在int型和byte型的一个交替过程。
此时可能你又会说,哪里还有int型?
来听我解释,在Java中,-128默认保存为int型
所以-128,作为int型,在计算机中保存为
10000000 00000000 00000000 10000000
然而它这么长的数据居然要保存在byte型里面(其实也没什么影响,不过它前面的那么多位数还是保存着的,没有丢失)
现在进行我们的补码转换
111111111 111111111 111111111 10000000
再进行移位
001111111 111111111 111111111 11100000
这时候移位之后别着急转换成原码
因为a是byte型的,而此时要进行输出,所以计算机只能输入以11100000为补码的数字,这一大串又是什么呢?这时候就可以进行补码转换。
补码转换为
1010 0000(即为-32)