转载请注明原创出处,谢谢!java
以前在JVM菜鸟进阶高手之路十(基础知识开场白)的时候简单提到了二进制相关问题,最近在看RocketMQ的源码的时候,发现涉及二进制的内容蛮多,jdk源码里面也是有不少涉及到二进制相关的操做,今天这篇文章仅仅是扫盲篇,后续会介绍灵活运用篇。编码
任何东西都有规范,提到JAVA就会提到2个规范,JAVA语言规范、JVM规范。JAVA语言规范主要定义JAVA的语法、变量、类型、文法等等,JVM规范主要定义Class文件类型、运行时数据、帧栈、虚拟机的启动、虚拟机的指令集等等。spa
JAVA八种基本数据类型: 整形:byte,short,int,long 浮点型:float,double 布尔型:boolean 字符型:char3d
数据类型 | 所占位数 |
---|---|
int | 32bit |
short | 16bit |
long | 64bit |
byte | 8bit |
char | 16bit |
float | 32bit |
double | 64bit |
boolean | 1bit |
**备注:**1字节=8位(1 byte = 8bit)code
**备注:**补码的好处:cdn
- 使用补码能够没有任何歧义的表示0。
- 补码能够很好的参与二进制的运算,补码相加符号位参与运算,这样就简单不少了。
在上图中,咱们了解到Float与Double都是支持IEEE 754对象
咱们以float来讲明:blog
IEEE754单精度浮点格式共32位,包含三个构成字段:23位小数f,8位偏置指数e,1位符号s。将这些字段连续存放在一个32位字里,并对其进行编码。其中0:22位包含23位的小数f; 23:30位包含8位指数e;第31位包含符号s。内存
一个实数V在IEEE 754标准中能够用V=(-1)s×M×2E 的形式表示,说明以下:ci
符号位 | 指数位 | 小数位 |
---|---|---|
1位 | 8位 | 23位 |
例如根据IEEE754,计算11000001000100000000000000000000的单精度浮点的值。
解题:
1 | 10000010 | 00100000000000000000000 |
---|---|---|
符号位 | 指数 | 尾数因为指数不是所有为0 因此小数位附加1 |
1 | 10000010 | **1.**00100000000000000000000 |
-1 | 2^(130-127) | (2^0 + 2^-3) |
结论: -1 * (2^0 + 2^-3) * 2^(130-127) =-9
一样,你也能够验证一下十进制浮点数0.1的二进制形式是否正确,你会发现,0.1不能表示为有限个二进制位,所以在内存中的表示是舍入(rounding)之后的结果,即 0x3dcccccd, 十进制为0.100000001, 偏差0.000000001由此产生了。
说到这里JVM菜鸟进阶高手之路十(基础知识开场白)的有些问题其实都解答了,因此涉及到钱的小数类型必须使用BigDecimal,禁止使用float和double。
咱们经常使用的进制有二进制、八进制、十进制和十六进制,十进制是最主要的表达形式。
二进制是0和1;八进制是0-7;十进制是0-9;十六进制是0-9+A-F(大小写都可)。
两位全为1,结果才为1:
0&0=0;
0&1=0;
1&0=0;
1&1=1;
复制代码
用法:
例如:设X=1010 1110,取X的低4位,用X & 0000 1111 = 0000 1110 就能够获得。
只要有一个为1,结果就为1:
0|0=0;
0|1=1;
1|0=1;
1|1=1;
复制代码
**用法:**经常使用来对一个数据的某些位置1;找到一个数,对应X要置1的位,该数的对应位为1,其他位为零。此数与X相或可以使X中的某些位置1。
例如:将X=1010 0000 的低四位置1,用X | 0000 1111 =1010 1111 就能够获得。
**两个相应位为“异”(值不一样),则该位结果为1,不然为0: **
0^0=0;
0^1=1;
1^0=1;
1^1=0;
复制代码
用法:
对于一个二进制数按位取反,即将0变1,1变0: ~1=0; ~0=1;
将一个数的各二进制位所有右移若干位,正数左补0,负数左补1,右边丢弃。操做数每右移一位,至关于该数除以2.
左补0 or 补1 得看被移数是正仍是负。 例:4 >> 2 = 1 例:-14(1111 0010) >> 2 = -4 (1111 1100 )
各个位向右移指定的位数。右移后左边突出的位用零来填充。移出右边的位被丢弃 各个位向右移指定的位数。右移后左边突出的位用零来填充。移出右边的位被丢弃 例如: -14>>>2
即-14(1111 1111 1111 1111 1111 1111 1111 0010)>>> 2 =(0011 1111 1111 1111 1111 1111 1111 1100) = 1073741820
int a = 1120429670;
for (int i = 0; i < 32; i++) {
int t = (a & 0x80000000 >>> i) >>> (31 - i);
System.out.print(t);
}
复制代码
说明:
- 0x80000000是数的十六进制表示,转成二进制表示为10000000000000000000000000000000
- 运算的优先级,移位运算高于逻辑运算,>>>高于&
- 位逻辑与运算 1&1 = 1 ,0&1 = 0
>>>
无符号右移,移出部分舍弃,左边位补0;
若是读完以为有收获的话,欢迎点赞、关注、加公众号【匠心零度】。
我的公众号,欢迎关注,查阅更多精彩历史!!!