5.位运算符
题外话:我们都知道,在计算机中,参与计算的都是二进制数据,而二进制数据又分为原码、反码、补码,运算的时候都是用补码来运算。 |
(1)<<:将参与运算的二进制数据向 左 移动,在低位产生的空位用 0 来补齐。
注意:在java中,整数的默认类型为 int 型,也就是32位,而为了在下文中叙述方便,我就使用8位的byte型了。
class Demo1{
public static void main(String[] args){
byte a = 7;
// 把a变量的二进制的值左移2位
System.out.println(a << 2); // 输出结果:28
}
}
整数 7 的二进制形式: | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
整数 7 的二进制左移两位: | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
class Demo1{
public static void main(String[] args){
byte a = -7;
// 把a变量的二进制的值左移2位
System.out.println(a << 2); // 输出结果:-28
}
}
-7 原码: | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
反码: | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
补码: | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
补码:(左移之后) | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
反码: | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
原码: | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
在这里需要简单解释一下,因为计算机的运算都是以补码的形式进行,而最高位的 0 或 1 代表的是符号位正或负,(以前不清楚这一点,正数的时候还好,一旦遭遇负数,脑子一团浆糊)。那么我们十进制的-7在进行移位运算之前,需要先转换成补码形式,然后才可以移位,(不要觉得我们进行到这里就结束了哈)实际上我们在控制台输出的还是 十进制的数,所以还要将移位之后的补码再转换成原码才行。
原码、反码、补码之间的转换我在之前的《java基础语法(二)》中就有过介绍,在这里我再说明一下吧:
正数:原码=反码=补码
负数:原码变反码:最高位符号位不变,其他数值位 0变1、1变0。
反码变补码:反码加1即可得。
(2)>>:(带符号右移)将参与运算的二进制数据向右移动,在高位产生的空位:如果高位是0,就用0补齐;如果高位是1,就用1补齐。
class Demo1{
public static void main(String[] args){
byte a = 7;
// 把a变量的二进制的值右移2位
System.out.println(a >> 2); // 输出结果:1
}
}
整数 7 的二进制形式: | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
整数 7 的二进制右移两位: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
class Demo1{
public static void main(String[] args){
byte a = -7;
// 把a变量的二进制的值右移2位
System.out.println(a >> 2); // 输出结果:-2
}
}
-7 原码: | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
反码: | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
补码: | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
补码:(右移之后) | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
反码: | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
原码: | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
负数的带符号右移运算的原理同左移原理相同,这里就不赘述了。
(3)>>>:(无符号右移)将参与运算的二进制数据向右移动,在高位所产生的空位用 0 补齐。
class Demo1{
public static void main(String[] args){
byte a = 7;
System.out.println(a >>> 2); // 输出结果:1
}
}
正数的无符号右移和正数的带符号右移的结果相同。所以相对来说,正数的无符号右移其实没有啥太大的意义。
class Demo1{
public static void main(String[] args){
int a = -7;
System.out.println(a >>> 2); // 输出结果:1073741822
}
}
-7原码: | 1000 0000 | 0000 0000 | 0000 0000 | 0000 0111 |
反码: | 1111 1111 | 1111 1111 | 1111 1111 | 1111 1000 |
补码: | 1111 1111 | 1111 1111 | 1111 1111 | 1111 1001 |
补码:(右移之后) | 0011 1111 | 1111 1111 | 1111 1111 | 1111 1110 |
注意:无符号右移只是对32位和64位的值有意义。上图中,右移后的补码最高符号位为0,所以为正数,所以原码就是它本身,那么转换成十进制之后的值为:1073741822