java 运算符随笔1——位移操作

本文介绍了Java中带符号位和不带符号位的右移操作。对于带符号位的右移,最高位的符号位保持不变,而无符号右移则将所有数值视为正数处理。文章通过正数和负数的例子详细解释了这两种右移的区别,帮助读者理解位移运算在Java中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java中任何赋值中带有运算的,都可以简写为运算符=

起因是今天在看HashMap的源码

static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

看代码的那些n的赋值操作,突然看到有点懵。常见的!= == +=突然出现这个|=措手不及。后来突然回想到,这是省略的写法,才想到,其实想表达的意思是n = n | n >>> 1。所以所有的赋值操作,如果需要进行运算操作的话,都可以简写成运算符=

java中的整数int

java中的int类型,是32位
因此普通的1,其实是00000000000000000000000000000001
-1,是11111111111111111111111111111111
其实就是正数1的补码。最高位为1,标识为负数。
即正数100000000000000000000000000000001取反
得到反码11111111111111111111111111111110
+1,得到补码:11111111111111111111111111111111也就是-1

带符号位的右移>>

>> 意思就是最高位的符号位不动,往右移动位数
左位移和右位移差不多,因此本次仅说明右位移,左位移自己类比就行。

>>举例

正数右位移

正数的话,就是往右移动相应的位数,左边补相应的0


		System.out.printf("%s%n", 1 >> 1);//result:0
		System.out.printf("%s%n", Integer.toBinaryString(1 >> 1));//result:00000000000000000000000000000000省略为0
		//分析
		//00000000000000000000000000000001  ==> 00000000000000000000000000000000
		//往右移动1位,失去了最右边的1,因此变成了31位的0,左边补0,凑齐32位,因此为0
		
		System.out.printf("%s%n", 1 >> 2);//result:0
		System.out.printf("%s%n", Integer.toBinaryString(1 >> 2));//result:00000000000000000000000000000000省略为0
		//分析
		//00000000000000000000000000000001  ==> 00000000000000000000000000000000
		//往右移动2位,失去了最右边的01,因此变成了30位的0,左边补00,凑齐32位,因此还是0
		
		System.out.printf("%s%n", 64 >> 1);//result:32
		System.out.printf("%s%n", Integer.toBinaryString(64 >> 1));//result:00000000000000000000000000100000省略为100000
		//分析
		//00000000000000000000000001000000  ==> 00000000000000000000000000100000
		//往右移动1位,失去了最右边的0,因此变成了31位的0000000000000000000000000100000,左边补0,凑齐32位,因此为32,即100000
		
		
		System.out.printf("%s%n", 64 >> 2);//result:16
		System.out.printf("%s%n", Integer.toBinaryString(64 >> 2));//result:00000000000000000000000000010000省略为10000
		//分析
		//00000000000000000000000001000000  ==> 00000000000000000000000000010000
		//往右移动2位,失去了最右边的00,因此变成了30位的0,左边补00,凑齐32位,因此为16,即10000

补充:因此可以知道,左移的话,左移1位,这个1就变成了2,左移2位,就变成了4,不再细说`左移`。
负数右位移

负数的话,就是往右移动相应的位数,左边补相应的1

		System.out.printf("%s%n", -1 >> 1); //result:-1
		System.out.printf("%s%n", Integer.toBinaryString(-1 >> 1));//result:11111111111111111111111111111111
		//分析
		//11111111111111111111111111111111  ==> 11111111111111111111111111111111
		//往右移动1位,失去了最右边的1,因此变成了31位的1,左边补1,凑齐32位,因此还是为-1
		
		
		System.out.printf("%s%n", -1 >> 2); //result:-1
		System.out.printf("%s%n", Integer.toBinaryString(-1 >> 2));//result:11111111111111111111111111111111
		//分析
		//00000000000000000000000000000001  ==> 00000000000000000000000000000000
		//往右移动2位,失去了最右边的11,因此变成了30位的1,左边补11,凑齐32位,因此还是-1
		
		
		System.out.printf("%s%n", -64 >> 1);//result:-32
		System.out.printf("%s%n", Integer.toBinaryString(-64 >> 1));//result:11111111111111111111111111100000
		//分析
		//11111111111111111111111111000000  ==> 11111111111111111111111111100000
		//往右移动1位,失去了最右边的0,因此变成了31位的1111111111111111111111111100000,左边补1,凑齐32位,因此变成了11111111111111111111111111100000,即-32
		
		
		System.out.printf("%s%n", -64 >> 2);//result:-16
		System.out.printf("%s%n", Integer.toBinaryString(-64 >> 2));//result:11111111111111111111111111110000
		//分析
		//11111111111111111111111111000000  ==> 11111111111111111111111111110000
		//往右移动2位,失去了最右边的00,因此变成了30位的111111111111111111111111110000,左边补11,凑齐32位,因此变成了111111111111111111111111110000,即-16

不带符号位的右移>>>

简单理解就是所有的数都当正数来处理

所谓无符号位右移,类似有符号位的右移,只不过唯一的区别就是,移动的位数,左边需要补齐的,全部用0补齐。

>>>举例

正数无符号右位移
		System.out.printf("%s%n", 1 >>> 1); //result:0
		System.out.printf("%s%n", Integer.toBinaryString(1 >>> 1));//result:0
		//分析
		//00000000000000000000000000000001  ==> 00000000000000000000000000000000
		//往右移动1位,失去了最右边的1,因此变成了31位的0,左边补0,凑齐32位,因此还是0
		
		
		System.out.printf("%s%n", 1 >>> 2); //result:0
		System.out.printf("%s%n", Integer.toBinaryString(1 >>> 2));//result:0
		//分析
		//00000000000000000000000000000001  ==> 00000000000000000000000000000000
		//往右移动2位,失去了最右边的01,因此变成了30位的0,左边补00,凑齐32位,因此还是0
		
		
		System.out.printf("%s%n", 64 >>> 1);//result:32
		System.out.printf("%s%n", Integer.toBinaryString(64 >>> 1));//result:100000
		//分析
		//00000000000000000000000001000000  ==> 00000000000000000000000000100000
		//往右移动1位,失去了最右边的0,因此变成了31位的0000000000000000000000000100000,左边补0凑齐32位,因此变成了00000000000000000000000000100000,即32
		
		
		System.out.printf("%s%n", 64 >>> 2);//result:16
		System.out.printf("%s%n", Integer.toBinaryString(64 >>> 2));//result:10000
		//分析
		//00000000000000000000000001000000  ==> 00000000000000000000000000010000
		//往右移动2位,失去了最右边的00,因此变成了30位的000000000000000000000000010000,左边补00,凑齐32位,因此变成了000000000000000000000000010000,即16
负数的无符号右位移

参考上面 java中的整数 int,负数的表示方法,可以更好理解下面的负数位移操作

		System.out.printf("%s%n", -1 >>> 1);//result:2147483647
		System.out.printf("%s%n", Integer.toBinaryString(-1 >>> 1));//result:1111111111111111111111111111111
		//分析
		//11111111111111111111111111111111  ==> 01111111111111111111111111111111
		//往右移动1位,失去了最右边的1,因此变成了31位的1,左边补0凑齐32位. 因此变为正数的2147483647
		
		
		System.out.printf("%s%n", -1 >>> 2);//result:1073741823
		System.out.printf("%s%n", Integer.toBinaryString(-1 >>> 2));//result:111111111111111111111111111111
		//分析
		//11111111111111111111111111111111  ==> 00111111111111111111111111111111
		//往右移动2位,失去了最右边的11,因此变成了30位的1,左边补00凑齐32位。因此变为正数的1073741823
		
		
		System.out.printf("%s%n", -64 >>> 1);//result:2147483616
		System.out.printf("%s%n", Integer.toBinaryString(-64 >>> 1));//result:1111111111111111111111111100000
		//分析
		//11111111111111111111111111000000  ==> 01111111111111111111111111100000
		//往右移动1位,失去了最右边的0,因此变成了31位的1111111111111111111111111100000,左边补0,凑齐32位,因此变成了正数的2147483616
		
		
		System.out.printf("%s%n", -64 >>> 2);//result:1073741808
		System.out.printf("%s%n", Integer.toBinaryString(-64 >>> 2));//result:111111111111111111111111110000
		//分析
		//11111111111111111111111111000000  ==> 00111111111111111111111111110000
		//往右移动2位,失去了最右边的00,因此变成了30位的111111111111111111111111110000,左边补00,因此变成了正数的1073741808
		
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值