Java语言下,位运算符理论

您所在的位置:网站首页 1110-0111补码运算 Java语言下,位运算符理论

Java语言下,位运算符理论

2023-06-15 13:49| 来源: 网络整理| 查看: 265

在位运算中,有三个操作符是相对难以理解的,这篇文章咱们就针对、>>>这三个操作符一探究竟,弄清楚它们到底是什么操作的;开始之前,需要补充一点计算机关于原码、反码、补码的基础知识!这部分已经有大牛说的很清楚了。

我们直接通过例子说明的方式。

1.左移

符号位不变,左边补符号值。

正数 byte num = 4; 直接简化操作 原码 0000 0100 num>>1进行右移一位 原码 0000 0010 num = 2

可以发现,正数右移就是数/2的N次方;例子:9>>1 ->(9-1)/2 = 4 。

byte num = 9 原码 0000 1001 num>>1进行右移一位 原码 0000 0100 num = 4 负数 byte num = -4 原码 1000 0100 符号为1(负数) 反码 1111 1011 进行反码时,符号位也是不变的 补码 1111 1100 同样符号位是不变的,溢出也不会改变符号位。 num>>1进行右移一位 补码 1111 1110 对补码进行位移符号位也是不参与移动 反码 1111 1101 反向的反码就是对位移后的补码减1 源码 1000 0010 num = -2

负数的右移就必须进行原码-反码-补码-运算后(补码)-反码-原码的转换过程。

另外,负数右移就是(-数-1)/2的N次方;例子:-9>>1 -> (-9-1)/2 = -5 。

byte num = -9 原码 1000 1001 反码 1111 0110 补码 1111 0111 num>>1进行右移一位 补码 1111 1011 反码 1111 1010 原码 1000 0101 num = -5

思考一个问题,为什么正数9右移一位是4,而负数-9右移一位是-5;数值不对等呢?再看下面例子:

byte num = -10 原码 1000 1010 反码 1111 0101 补码 1111 0110 num>>1进行右移一位 补码 1111 1011 反码 1111 1010 原码 1000 0101 num = -5

仔细观察-10和-9两位数在>>1之后的补码是完全一样的,我想原因就出在-9的补码后在右移一位,直接把补码移调了,相当于变向-1了,从而导致-9位移之后的补码和-10的相等,那-9位移的之后的值自然也和-10一样,同理正数9右移为啥(9-1)/2 = 4。所以综上推导出,奇数(右移就是(数-1)/2的N次方)的结论。

3.无符号右移>>>

与>>区别就是首位不再是符号位,所以会直接把原本的符号位直接往右位移了,左边补0。

正数 byte num = 4 直接简化操作 原码 0000 0100 num>>>1进行无符号右移一位 原码 0000 0010 num = 2

正数的无符号右移跟有符号右移是一样的。

负数

重点关注一下负数的无符号右移。

byte num = -4 原码 1000 0100 反码 1111 1011 补码 1111 1100 num>>>1进行无符号右移一位 补码 0111 1110 因为没有符号位,所以原本的符号位直接当做数值往右移动了。 反码 0111 1110 原码 0111 1110 因为变成了正数,所以原码、反码、原码一样。 num = 126

但是这里要格外注意,你实际去用Java代码打印时可能会不一样。

byte num = -4; num = (byte) (num>>>1); System.out.println(num); 得到的结果是 num = -2

结果确不一样,为什么会这样呢?因为在jvm底层位运算都是对int值的操作,所以首先会把byte转换成int,所以过程就变成了下面这样。

byte num = -4 jvm操作扩容 int num = -4 原码 10000000 00000000 00000000 00000100 反码 11111111 11111111 11111111 11111011 补码 11111111 11111111 11111111 11111100 num>>>1进行无符号右移一位 补码 01111111 11111111 11111111 11111110 反码 01111111 11111111 11111111 11111110 补码 01111111 11111111 11111111 11111110 因为变成了正数,所以原码、反码、原码一样。 然后回到(byte) (num>>>1)这一步,进行了数据类型强转,就变成了11111110。 又变成了负数,那需要转会原码。 补码 11111110 反码 11111101 原码 10000010 num = -2

这就解释了上面在java程序上执行-4>>>1为啥结果是-2,所以运用其它运算符在进行操作时,也格外需要注意数据类型转换带来的结果差异问题,同时有一个小点Integer.toBinaryString()此方法打印的是补码。

4.总结 二进制的最高位是符号位:0表示正数,1表示负数; 正数的原码、反码、补码都一样; 负数的反码 = 它的原码符号位不变,其他位取反(0 ->1 ; 1->0 ); 负数的补码 = 它的反码 +1; 0的反码、补码都是0,计算机中0是正数; 在计算机运算的时候,都是以补码的方式来运算的; 5.口诀 左移乘; 右移偶数除,奇数减一再除; 无符号右移正数同右移,负数会变正;


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3