java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java位运算左移右移:原码反码补码与无符号右移

Java位运算左移右移详解:原码反码补码与无符号右移的区别

作者:Masked5

这篇文章详细解释了为什么没有无符号左移运算符,并深入讲解了原码、反码和补码的区别,以及计算机为何使用补码存储数字,通过正负数示例,清晰展示了左移、右移和无符号右移的运算规则,还结合HashMap和ArrayList扩容源码,帮你轻松掌握位运算在实际开发中的应用

为什么没有无符号左移呢?

在计算机中,位运算中左移跟符号没有关系的,因为最高位就是符号位。

例如8位的byte中最高位如果是1那就表示负数。如果是左移一位,那么最高位就会丢掉,最低位补0。

例如:1111 1111 << 1 就会变成 1111 1110。因此,不仅是Java,任何语言都没有无符号左移运算符。

位操作操作的是原码、反码还是补码?

原码、反码和补码都是用来表示数字的编码方式。

计算机内部使用补码来存储数字。这样做可以简化计算机底层电路设计,并且可以多表示一个最低数。例如,在8位二进制中,使用原码或反码表示时范围为[-127, +127],而使用补码表示时范围为[-128, +127]。

左移 <<

将一个数对应的二进制表示整体左移,不考虑符号位,左边超出的部分舍弃,右边补零。

正数

以数字10为例,二进制表示为

00000000 00000000 00000000 00001010

第一位为符号位,0表示正数,1表示负数。左移1位之后为

00000000 00000000 00000000 00010100

十进制表示为20,相当于乘以2。HashMap扩容时将新容量增加为原来容量的两倍,就是使用左移实现的。

负数

以负数-10为例,二进制表示为

1111 1111 1111 1111 1111 1111 1111 0110

左移1位结果为

1111 1111 1111 1111 1111 1111 11110 1100

十进制为-20,也是相当于乘以2。

右移 >>

将一个数对应的二进制表示整体右移,考虑符号位,左边的用原有符号位补充,右边超出的部分舍弃。

正数

以10为例

00000000 00000000 00000000 00001010

右移1位

00000000 00000000 00000000 00000101

十进制表示为5,相当于除以2。ArrayList扩容时将新容量增加为原来的1.5倍,就是使用右移实现的。

负数

以负数-10为例

1111 1111 1111 1111 1111 1111 1111 0110

右移1位

1111 1111 1111 1111 1111 1111 1111 1011

十进制表示为-5,也是相当于除以2。

无符号右移 >>>

将一个数的二进制表示整体右移,不考虑符号位,左边部分总是以0填充,右边部分舍弃。

正数

和上面的右移一致。

负数

以-10为例

1111 1111 1111 1111 1111 1111 1111 0110

无符号右移1位

01111 1111 1111 1111 1111 1111 1111 1011

十进制表示为2147483643。HashMap中在求一个数最接近的2的N次幂时使用到了无符号右移。

超过32位的左移会怎样?

如果一个int型数字左移超过32位,如33位,相当于左移1位,右移、无符号右移同理。

a << n == a << (n % 32)

位移是一个取模的过程

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文