龙空技术网

Java教程:位移运算符

半成品牛筋面 141

前言:

此刻朋友们对“java中取余的符号”都比较关心,看官们都想要分析一些“java中取余的符号”的相关文章。那么小编同时在网络上汇集了一些对于“java中取余的符号””的相关内容,希望姐妹们能喜欢,咱们快快来学习一下吧!

在源代码中,经常可以看到一些位移操作符的使用。例如,在查看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;    }12345678复制代码类型:[java]

对位移运算符概念不熟悉的同学,看到这个估计是一脸懵逼,所以要想完全看懂源码,就需要对位移运算符有一定的了解。下面我用以任意一个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中取余的符号