Java教程:位移运算符

开课吧开课吧锤锤2021-07-19 11:46

在源代码中,经常可以看到一些位移操作符的使用。例如,在查看HashMap源代码时,在计算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;    }

对位移运算符概念不熟悉的同学,看到这个估计是一脸懵逼,所以要想完全看懂源码,就需要对位移运算符有一定的了解。下面我用以任意一个10进制的int数据  

inte=12345为例进行解析:  

12345二进制表达:  

位移运算符

1、左位移运算符<<  

如果e<<1,左位移1位:  

 

位移运算符

 

位移后十进制数值变成:24690,刚好是12345的二倍,所以有些人会用左位移运算符代替乘2的操作,但是这并不代表是真的就是乘以2,很多时候,我们可以这样使用,但是一定要知道,位移运算符很多时候可以代替乘2操作,但是这个并不代表两者是一样的(这一点需要格外注意,很多人都存在这样的误解),接着往下看:  

如果继续左移,12345左移14位:  

e<<14  

 

位移运算符

 

这里要注意了,左位移18位后,二进制首位为1,如下图所示:  

 

位移运算符

 

此时二进制表达首位为1,此时数值为-1058799616,同理,如果继续位移,左位移20位,则值为59768832又变成了正数  

所以根据这个规则,如果任意一个十进制的数左位移32位,右边补位32个0,十进制岂不是都是0了?当然不是!!!当int类型的数据进行左移的时候,当左移的位数大于等于32位的时候,位数会先求余数,然后再进行左移,也就是说,如果真的左移32位e<<32的时候,会先进行位数求余数,即为e<<(32%32)相当于e<<0,所以e<<33的值和e<<1是一样的,都是24690  

2、右移运算符>>  

同样,还是以12345这个数值为例,  

e右移1位:e>>1  

 

位移运算符

 

右移后得到的值为6172和int类型的数据12345除以2取整所得的值一样,所以有些时候也会被用来替代除2操作  

但是如果继续右移,直接右移14位,即为e>>14,则结果为0,其过程和左移相似,就不一一演示了;另外,对于超过32位的位移,和左移运算符一样,,会先进行位数求余数  

3、无符号右移运算符:>>>  

无符号右移运算符和右移运算符是一样的,不过无符号右移运算符在右移的时候是补0的,而右移运算符是补符号位的  

一下是-12345二进制表达式  

 

位移运算符

 

对于源码、反码、补码不熟悉的同学,请自行学习,这里就不再进行补充了讲解了,这里提醒一下,在右移运算符中,右移后补0,是由于正数12345符号位为0,如果为1则应补1  位移运算符

最后补充一下:  

1、原码、反码和补码  

一个数可以分成符号位(0正1负)+真值,原码是我们正常想法写出来的二进制。由于计算机只能做加法,负数用单纯的二进制原码书写会出错,于是大家发明了反码(正数不变,负数符号位不变,真值部分取反);再后来由于+0,-0的争端,于是改进反码,变成补码(正数不变,负数符号位不变,真值部分取反,然后+1)。二进制前面的0都可以省略,所以总结来说:计算机里的负数都是用补码(符号位1,真值部分取反+1)表示的。  

2、位运算符和2的关系  

位运算符和乘2除2在大多数时候是很相似的,可以进行替代,同时效率也会高的多,但是两者切记不能混淆;  

很多时候有人会把两者的概念混淆,尤其是数据刚好是2、4、6、8、100等偶数的时候,看起来就更相似了,但是对于奇数,如本文使用的12345,右移之后结果为6172,这个结果就和数学意义上的除以2不同了,不过对于int类型的数据,除2会对结果进行取整,所以结果也是6172,这就更有迷惑性了  

以上就是开课吧广场小编为大家整理发布的“Java教程:位移运算符”一文,更多Java教程相关内容尽在开课吧Java教程频道。

免责声明:本站所提供的内容均来源于网友提供或网络搜集,由本站编辑整理,仅供个人研究、交流学习使用。如涉及版权问题,请联系本站管理员予以更改或删除。
有用2
分享