二进制溢出后怎么得到正确数值(编程基础必备知识:二进制位运算符)

今天看到一些关于右移和无符号右移的博客解释,发现好多都要么没有实践随意说,有的甚至乱说,说无符号右移补啥的都有.就自己整理了一下.看本文之前,你需要对二进制、十进制及其运算有一定的概念基础.,我来为大家科普一下关于二进制溢出后怎么得到正确数值?以下内容希望对你有帮助!

二进制溢出后怎么得到正确数值(编程基础必备知识:二进制位运算符)

二进制溢出后怎么得到正确数值

今天看到一些关于右移和无符号右移的博客解释,发现好多都要么没有实践随意说,有的甚至乱说,说无符号右移补啥的都有.就自己整理了一下.看本文之前,你需要对二进制、十进制及其运算有一定的概念基础.

& 按位与

同为1得1,否则为0;

| 按位或

有1得1,其他为0;

^ 按位异或

相异得1,否则得0;

如1-0得1,0-1得1.

~ 取反

1变0,0变1;

<< 左移

x<<n;x * 2^n左移(符号位不动,正负数皆右补0)

>> 右移

x>>n;x /2^n丢弃右边指定位数,左边补上符号位(0正,1负,符号位位于最左位置)

>>> 无符号右移

正数时候和右移是一样的.丢弃右边指定位数,左边全是补上0

负数举例:

System.out.println(-2>>1); System.out.println(-2>>>1); # 结果: -1 2147483647

为了说清无符号右移,需要知道原码、反码和补码;

原码、反码和补码

原码:一个整数,按照绝对值大小转换成的二进制数,称为原码。

反码:将二进制数按位取反,所得的新二进制数称为原二进制数的反码。

补码:反码加1称为补码。

负数以其正值的补码形式表达.

验证一下:

System.out.println(Integer.toBinaryString(2)); // 对2取反,得到: System.out.println(Integer.toBinaryString(~2)); // 取-2,可以看到,就是2取反后 1的结果 System.out.println(Integer.toBinaryString(-2)); // 再看一下5和-5的 System.out.println(Integer.toBinaryString(5)); System.out.println(Integer.toBinaryString(~5)); System.out.println(Integer.toBinaryString(-5)); # 2 -2的结果 10 11111111111111111111111111111101 11111111111111111111111111111110 # 5 -5的结果 101 11111111111111111111111111111010 11111111111111111111111111111011

再看右移和无符号右移

先再解释一下符号位:我们知道int占用4字节大小,数值范围-2147483648~2147483647,转成二进制,就是10000000000000000000000000000000 ~ 01111111111111111111111111111111,可以清晰看到,第一位符号位,是决定的这个数的正负.

前面知道了-2的二进制表示是11111111 11111111 11111111 11111110,那么右移1位,那就是把最右边的0挤掉了,得到1111111 11111111 11111111 11111111,这样少了一位,右移的概念说补符号位,-2是负数,那就是在最左补一个1,得到11111111 11111111 11111111 11111111(如果还有空位的话要补0,这里只移了一位,没空位了).

简单验证一下,1的二进制是00000000000000000000000000000001,取反:11111111111111111111111111111110,再取补码,显然就是我们刚做-2>>1得到的结果,也就是-1.(计算器,编程语言,好像都没有一个直接把负的二进制数转十进制或直接运算的!).(实际上,做个逆运算,把得到的11111111 11111111 11111111 11111111减去1,再取反,就得到其正数时的值1,也可以知道,我们算出来的结果是-1.)

上面只是验证了右移..再看无符号位移,为什么-2>>>1的结果是2147483647,先看一下这个结果的二进制数01111111111111111111111111111111(最大的一个int).这个通过概念比较好理解,前面右移的那里,我们知道-2的二进制表示,也知道右移一位后的结果,区别是,前面不是补符号位,而是补0,补0,那就是01111111111111111111111111111111,也就是2147483647.

所以你理解一下,无符号右移的无符号,指的就是正负符号,全名可以理解为:无视正负符号的右移,左边全部补0,所以你是不是也可以回答:为什么无符号右移,得到必是非负数这类问题了?

应用

左移和右移,可以在做一些做2的倍次运算时使用,提高你的运算效率.无符号右移的应用,我们比较熟悉hashCode()中就用到了.

static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }

拓展

思考一下,为什么没有无符号左移?

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页