Java基础之 位移操作

左移(<<)、右移(>>)、无符号右移(>>>),其中左移(<<)和右移(>>)是有符号的位移。
位运算符只能对整形或字符型进行操作。

前置知识
一个整数在计算机中是如何表示的?
计算机中的整数都是以二进制表示的,并且正整数和负整数的表示方法也不相同。

正负数的表示还涉及到原码、反码和补码
正数的原码、反码和补码都相同
负数以正值的补码形式表示

例如Java的int类型的4,重点看后四位
00000000000000000000000000000100
高位都是0

例如Java的int类型的-4,重点看后四位
11111111111111111111111111111100
高位都是1
转换过程:
原码:00000000000000000000000000000100
反码:11111111111111111111111111111011
补码:11111111111111111111111111111100 反码+1=补码

1、左移(<<):高位舍弃,低位补0
所有位向左移动一次,左侧一位舍弃(包括符号位都移动),末尾补0

例如:8<<1
00001000
0001000_->补0
------------
       |
 下划线位置需要补位,用0补位

00010000 这是左移一位的结果
从结果可以看出8右移一位结果为16,所以左移一次都是原有数据乘2

例如:-8<<1
11111000
1111000_->补0
------------
       |
 下划线位置需要补位,用0补位

11110000 这是右移一位的结果
从结果可以看出-8右移一位结果为-16,所以左移一次都是原有数据乘2

测试代码:

public static void main(String[] args) {

        int a = 1;
        System.out.println(a+":"+Integer.toBinaryString(a));
        while(a!=0) {
            a = a<<1;
            System.out.println(a+":"+Integer.toBinaryString(a));
        }

    }
}

/* 输出结果
1:1
2:10
4:100
8:1000
16:10000
32:100000
64:1000000
128:10000000
256:100000000
512:1000000000
1024:10000000000
2048:100000000000
4096:1000000000000
8192:10000000000000
16384:100000000000000
32768:1000000000000000
65536:10000000000000000
131072:100000000000000000
262144:1000000000000000000
524288:10000000000000000000
1048576:100000000000000000000
2097152:1000000000000000000000
4194304:10000000000000000000000
8388608:100000000000000000000000
16777216:1000000000000000000000000
33554432:10000000000000000000000000
67108864:100000000000000000000000000
134217728:1000000000000000000000000000
268435456:10000000000000000000000000000
536870912:100000000000000000000000000000
1073741824:1000000000000000000000000000000
-2147483648:10000000000000000000000000000000
0:0
*/

2、右移(>>):高位补符号位,低位舍弃
所有位向右右移一次,右侧一位舍弃,高位空出的一位,用符号位补全

例如:8>>1
00001000
0_000100 0->舍弃
------------
 |
 下划线位置需要补位,用0补位

00000100 这是右移一位的结果
从结果可以看出8右移一位结果为4,所以右移一次都是原有数据除2

例如:-8>>1
11111000
1_111100 0->舍弃
------------
 |
 下划线位置需要补位,用1补位

11111100 这是右移一位的结果
从结果可以看出-8右移一位结果为-4,所以右移一次都是原有数据除2

3、无符号右移(>>>):低位舍弃,高位补0
每右移一次,包括符号位一起右移,高位用0补全,右侧一位舍弃
推演的逻辑和上面右移(>>)是一样的,区别在于高位补0,我们以Java int类型来看,-8>>>1

-8:
11111111111111111111111111111000

2147483644:
01111111111111111111111111111100