java中的移位操作符

java中的移位操作符


最近在看移位操作符的时候遇到了一个有趣的问题:

  • -1无符号右移32位时,会再次变成-1而不是我预期中的0.

首先介绍一下java中的移位操作符: <<(有符号左移操作符) >>(有符号右移操作符) 和>>>(无符号右移操作符)

(负数在java中是以补码的形式存储的:
-1的原码为:
1000 0000 0000 0000 0000 0000 0000 0001
-1的反码为:
1111 1111 1111 1111 1111 1111 1111 1110
-1的补码为:
1111 1111 1111 1111 1111 1111 1111 1111
所以,在java中-1的二进制码为:1111 1111 1111 1111 1111 1111 1111 1111)

  1. 左移操作符(<<):将二进制数向左移动一位,低位补0.
	int i = 1;
    System.out.println(Integer.toBinaryString(i));
    i<<=1;
    System.out.println(Integer.toBinaryString(i));
    
    int j = -1;
    System.out.println(Integer.toBinaryString(j));
    j<<=1;
    System.out.println(Integer.toBinaryString(j));
	结果为:
	1 	//1
	10	//2
	11111111111111111111111111111111 //-1
	11111111111111111111111111111110 //-2

实际上,向左的移位操作符就是将原本的数字乘2.

  1. (有符号)右移操作符(>>)是将二进制数向右移动一位,高位补符号的数字
	int i = 7;
    System.out.println(Integer.toBinaryString(i));
    i>>=1;
    System.out.println(Integer.toBinaryString(i));

    int j = -7;
    System.out.println(Integer.toBinaryString(j));
    j>>=1;
    System.out.println(Integer.toBinaryString(j));
	结果为:
	111//7
	11 //3
	11111111111111111111111111111001 //-7
	11111111111111111111111111111100 //-4

实际上我们看到有符号的右移操作符就是将数字除以二取商,即取模运算.

3.(无符号)右移操作符(>>>)将二进制数向右移动一位,高位补0.

	int i = 7;
    System.out.println(Integer.toBinaryString(i));
    i>>>=1;
    System.out.println(Integer.toBinaryString(i));

    int j = -7;
    System.out.println(Integer.toBinaryString(j));
    j>>>=1;
    System.out.println(Integer.toBinaryString(j));
111 //7
11  //3
11111111111111111111111111111001 //-7
1111111111111111111111111111100  //2147483644

下面说明遇到的问题:
如上面所说,-1在java中的二进制码为:1111 1111 1111 1111 1111 1111 1111 1111
当我进行无符号的右移操作时,若右移了32位以上,根据高位补0,结果应该变为0.
但是实际上我对-1进行右移时,大于32时不为0.

在网上查资料以后发现,在对int类型的数据进行移位操作时,对于移位数,java中只截取了二进制数的后五位,而对long类型的进行移位时截取后六位.
即最大值为 1 1111 = 31,所以,在进行移位操作时,最大的移位数为31.下面进行实验:

	int i = -1;
    System.out.println(Integer.toBinaryString(i));
    i>>>=10;
    System.out.println(Integer.toBinaryString(i));

    int j = -1;
    System.out.println(Integer.toBinaryString(j));
    j>>>=32;
    System.out.println(Integer.toBinaryString(j));

    int k = -1;
    System.out.println(Integer.toBinaryString(k));
    k>>>=42;
    System.out.println(Integer.toBinaryString(k));
	结果为:
	11111111111111111111111111111111
	1111111111111111111111
	
	11111111111111111111111111111111
	11111111111111111111111111111111
	
	11111111111111111111111111111111
	1111111111111111111111

右移位数 10 32 42的二进制码如下:
1010
100000
101010

我们看到 10 和42 的后五位都为 01010,所以移位后结果一致.
而右移32时后五位为0 0000 和右移0位的后五位一致,所以结果不变
我们再进行一组实验:

	int i = -7;
    System.out.println(Integer.toBinaryString(i));
    i>>>=-22;
    System.out.println(Integer.toBinaryString(i));

    int j = -7;
    System.out.println(Integer.toBinaryString(j));
    j>>>=10;
    System.out.println(Integer.toBinaryString(j));
11111111111111111111111111111001
1111111111111111111111

11111111111111111111111111111001
1111111111111111111111

在上面的的代码中对-7进行了-22的右移和10的右移,我们发现结果一致.
对比-22 和 10 的二进制数为:
11111111111111111111111111101010
1010
后五位 01010一致,所以右移的结果一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值