博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java二进制操作计算的总结
阅读量:6242 次
发布时间:2019-06-22

本文共 4739 字,大约阅读时间需要 15 分钟。

写在前面

一直以来对二进制的操作计算不太清楚,这次找了一些资料完整地进行了一些总结。


一、进制类别和关系:

  1. 二进制,十进制,十六进制的区别和进制之间的相互转换方法(概念性的东西,可以百度)。
  2. n位的二进制能够表示2的n次方个数,如4位的二进制可以表示十进制的0~15共16个数 。
  3. 十六进制的基数是16,数码为0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F,其中用A,B,C,D,E,F(字母不区分大小写)这六个字母来分别表示10,11,12,13,14,15。
  4. 由于十六进制的基数是2的幂,因此二进制和十六进制的转换很方便。一个二进制数,只要把它从低位到高位每4位组成一组,4个二进制位可以表示从0到15的数字,这刚好是1个16进制位可以表示的数据,也就是说,将二进制转换成十六进制只要每4位进行转换就可以了。
    • 0011 0101 1011 1111 = 0x35BF(以0x开始的数据表示16进制) 。
    • MIN_VALUE = 0x80000000对应的二进制是10000000 00000000 00000000 00000000
    • MAX_VALUE = 0x7fffffff对应的二进制是01111111 11111111 11111111 11111111

二、移位操作

  1. 左移位<< :
/* 00000001 << 1 = 00000010 */    1 << 1 == 2 /* 00000001 << 3 = 00001000 */    1 << 3 == 8复制代码
  1. 右移位>> :
    向右移位是有符号操作符。和许多语言一样,Java使用最高位来表示数值的正负,负数的最高位永远为1。一个以1开头的二进制数移位后还将以1开头,一个以0开头的二进制数移位后还将以0开头。
/* 11111111 11111111 11111111 11110000 >> 4 = 11111111 11111111 11111111 11111111 */    0xFFFFFFF0 >> 4 == 0xFFFFFFFF 	 /* 00001111 11111111 11111111 11111111 >> 4 = 00000000 11111111 11111111 11111111 */    0x0FFFFFFF >> 4 == 0x00FFFFFF复制代码
  1. 无符号右移>>> :这种移位会忽略符号位并总是用“0”来填充。
/* 10000000 00000000 00000000 00000000 >>> 1 = 01000000 00000000 00000000 00000000 */    0x80000000 >>> 1 == 0x40000000复制代码
  1. 移位的作用
  • 迅速求2的幂。1向左移位1位是2,移2位是4,移3位是8…… 相似的,向右移1位相当于是把该数除以2。(将一个数k移动n位,可以看做将k*2^n)
  • 创建掩码。位掩码可用于屏蔽或者修改一个二进制数中的某些指定位。如得到00001000的掩码可以通过1 << 3得到。

三、位运算操作符

  1. ~ :按位取反,如果位为0,结果是1,如果位为1,结果是0
~1111 == 0000    ~0011 == 1100复制代码
  1. & : 按位与,两个操作数中位都为1,结果才为1,否则结果为0
1010 & 0101 == 0000    1100 & 0110 == 0100复制代码
  1. ^ : 按位异或,两个操作数的位中,相同则结果为0,不同则结果为1
1010 ^ 0101 == 1111    1100 ^ 0110 == 1010复制代码
  1. | : 按位或,两个位只要有一个为1,那么结果就是1,否则就为0
1010 | 0101 == 1111    1100 | 0110 == 1110复制代码
  1. 位运算符的作用:
  • 可以选择性的把一个二进制数的某位设为0,让数与一个全1但是某位为0的数相与。如,01010101 & ~(1<<2) == 01010101 & 11111011 == 01010001

四、原码, 反码, 补码:

对于一个数, 计算机要使用一定的编码方式进行存储。原码,反码,补码是机器存储一个具体数字的编码方式。

  1. 机器数和真值
    • 机器数:一个数在计算机中的二进制表示形式,叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1。如,00000011 和 10000011这两个机器数分别表示+3和-3。
    • 真值:将带符号位的机器数对应的真正数值称为机器数的真值。如,10000011其最高位 1 代表负,其真正数值是 -3而不是形式值131(10000011转换成十进制等于131)。
  2. 原码:符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值.如,[+1]原 = 0000 0001,[-1]原 = 1000 0001
    • 因为第一位是符号位, 所以 8 位二进制数的取值范围是:[1111 1111 , 0111 1111] 即 [-127 , 127]
    • 原码是人脑最容易理解和计算的表示方式.
  3. 反码:正数的反码是其本身,负数的反码是在其原码的基础上,符号位不变,其余各个位取反。如,[+1] = [00000001]原 = [00000001]反 / [-1] = [10000001]原 =[11111110]反
    • 如果一个反码表示的是负数,人脑无法直观的看出来它的数值.通常要将其转换成原码再计算.
  4. 补码:正数的补码就是其本身,负数的补码是在其原码的基础上,符号位不变,其余各位取反, 最后 +1. (即在反码的基础上 +1)
    • 对于负数, 补码表示方式也是人脑无法直观看出其数值的。通常也需要转换成原码再计算其数值。
  5. 为何要使用反码和补码
    • 设计简单:因为人脑可以知道第一位是符号位,在计算的时候我们会根据符号位,选择对真值区域的加减。但是对于计算机,加减乘数是最基础的运算,要设计地尽量简单。而让计算机辨别"符号位"会让计算机的基础电路设计变得十分复杂。
    • 加法设计:可以用符号位参与运算来简化设计。根据运算法则减去一个正数等于加上一个负数, 即: 1-1=1+(-1)=0,所以机器可以只有加法而没有减法,这样计算机运算的设计就更简单了。
    • 原码直接符号位相加,得到的结果是错误的,因此需要使用反码和补码
  6. 反码加法:
    反码加法结果的真值部分是正确的,但是在"0"这个特殊的数值上,虽然人们理解上 + 0和 -0 是一样的, 但是 0 带符号是没有任何意义的, 而且会有 [0000 0000]原和[1000 0000]原两个编码表示 0。
// 计算十进制的表达式: 1 - 1 = 0    1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0复制代码
  1. 补码加法:
1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原复制代码
  • 这样 0 用 [0000 0000] 表示,而反码出现问题的-0则不存在了,而且可以用多余的[1000 0000] 表示 -128:
(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补复制代码
  • 在用补码运算的结果中,[10000000]补就是-128,但是注意因为实际上是使用以前的-0的补码来表示 -128, 所以 -128并没有原码和反码表示(对-128的补码表示[10000000]补算出来的原码是[0000 0000], 这是不正确的)
  • 使用补码运算能够多表示一个最低数,这就是为什么8位二进制,使用原码或反码表示的范围为 [-127, +127], 而使用补码表示的范围为 [-128, 127]。

五、Integer的MIN_VALUE和MAX_VALUE

  1. 计算机存储数字是使用补码, 所以对于编程中常用到的 32 位int类型,可以表示范围是: [-2^31, 2^31-1] 因为第一位表示的是符号位,而使用补码表示时又可以多保存一个最小值。
  2. 从表示的数字总数来说,还是 2^31*2(因为正负值,所以*2)
    • 对于正数的2^31来说,[00000000 00000000 00000000 00000000]表示了0,所以正数的最大值是2^31-1(因为一种排列一个数,数与数之间都是隔1,所以正数总数-1即正数的最大值)。
    • 对于负数的2^31来说,[10000000 00000000 00000000 00000000]表示了最大值,所以负数的最大值是-2^31,多表示了一个数。
  3. Integer.MAX_VALUE,即2^31-1=2147483647,最小值为-2^31=Integer.MIN_VALUE -2147483648
  4. 越界问题
  • Integer.MIN_VALUE-1 = Integer.MAX_VALUE:
Integer.MIN\_VALUE - 1 = Integer.MIN_VALUE + (-1)        10000000000000000000000000000000+   11111111111111111111111111111111[补]---------------------------------------------------    1,01111111111111111111111111111111[补]    舍弃最高位的进位,所以得到的就是Integer.MAX_VALUE复制代码
  • Integer.MAX_VALUE + 1= Integer.MIN_VALUE:
    对Integer.MAX_VALUE加1,2147483648(越界了),结果是-2147483648,即是Integer.MIN_VALUE。
01111111111111111111111111111111    +   00000000000000000000000000000001[正数补码等于本身]---------------------------------------------------        10000000000000000000000000000000[补]复制代码
  • 对Integer.MIN_VALUE取绝对值:
    因为值为-2147483648,绝对值2147483648超过Integer.MAX_VALUE 2147483647,所以值还是Integer.MIN_VALU。因为,Integer.MAX_VALUE=01111111111111111111111111111111,再加1为10000000000000000000000000000000,等于Integer.MIN_VALUE

四、Java中的方法

  • java代码里操作二进制数字的方法是使用Integer.parseInt()方法。如,Integer.parseInt(“101″,2)代表着把二进制数101转换为十进制数5。

五、参考资料

、 、 、 、

转载地址:http://rtvia.baihongyu.com/

你可能感兴趣的文章
Hystrix问题记录
查看>>
Linux 上ps 命令的使用
查看>>
祛斑用什么产品比较好?简单一步轻松搞定
查看>>
OkHttp发起请求源码阅读(一)
查看>>
复杂度分析(上):如何分析、统计算法的执行效率和资源消耗?
查看>>
java spring cloud版b2b2c社交电商-配置中心svn示例和refresh
查看>>
回顾我的三年前端|掘金技术征文
查看>>
如何保障微服务架构下的数据一致性?
查看>>
开源框架和开源项目
查看>>
算法学习之路|二分图的最大匹配—匈牙利算法(Dfs实现)
查看>>
iOS UIView高级动画 关键帧动画
查看>>
java版spring cloud+spring boot+redis多租户社交电子商务平台 (六)分布式配置中心(Spring Cloud Config)...
查看>>
一个初学者是如何制作移动端B站画友社区的
查看>>
互联网分布式微服务云平台规划分析--平台整体规划
查看>>
Swift对象转为C指针
查看>>
Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)
查看>>
ThinkSNS系统升级,版本多样化
查看>>
ecshop使用smtp发送邮件
查看>>
RubyInstaller
查看>>
21. SQL -- TSQL架构,系统数据库,文件,SQL 认证,TSQL语句
查看>>