1. 背景
public class Test { public static void main(String[] args) { System.out.println(2.0-1.1); } }
输出的结果是:0.8999999999999999
2. 浮点在Java中二进制的表示
- 符号位子(Sign):0代表正,1代表负;
- 指数位(Exponent):用于存储科学技术法中的指数数据;
- 尾数部分(Fraction):存储科学计数法后面的尾数部分;
这3个部分,在单精度和双精度数据所占的字节数是不同的,具体如下图:
32位 符号位:1 bit 指数位:8 bits 尾数部分: 23 bits Bias:127(2^7-1)
64位 符号位:1 bit 指数位:11 bits 尾数部分: 52 bits Bias:1023(2^10-1)
Bias是固有常量,之后将二进制转化为十进制的小数点会用到。
2.1 分类
在说将上面的二进制格式转换为十进制小数点前,需要将浮点型数据做个分类:(以32位为例)
S(1位) E(8位) M(23位) N(32位)
符 0 0 (-1)S*2-126*(0.M) 为规格化数(+/- 0.0)
0 不等于0 (-1)S*2-126*(0.M)为非规格化数
号 1到254之间 不等于0 (-1)S*2E-127*(1.M) 为规格化数
255 不等于0 NaN(非数值)
位 255 0 无穷大
(1)其中NaN之间也可以是不等的,原因就是M部分的数值可以是不同的。
(2)浮点中是有0是有正负的,但它们的值是一样大的。
(3)第二类非规格化数可以扩大浮点型的大小范围,但转化方式要特别注意。java中的最小值就是这种类型,二进制位000......001,最后结果1.4E-45。
(4)java中任何正数/0为正无穷,任何负数/0为负无穷。
2.2 二进制向十进制小数点转换
转化公式:
(1)32位
x=(-1)s×(1.M)×2E-127 e=E-127(127就是Bias)
(2)64位
x=(-1)s×(1.M)×2E-1023 e=E-1023(1023就是Bias)
其中,s是符号位,M是尾数,E是阶码,e是实际的指数值
将S,M,E带入转化为十进制,最后计算的x结果,即是十进制的小数。
逆向转化:
ex:-3.75
(1) 首先转化为2进制表示(关键就是转化成2进制科学技术形式)
−3.75=−(2+1+1/2+1/4)=−1.111×2^1
(2) 整理符号位并进行规格化表示
−1.111×2^1=(−1)(1)×(1+0.1110 0000 0000 0000 0000 000)×2^1
(3) 进行阶码的移码处理
(−1)(1)×(1+0.1110 0000 0000 0000 0000 000)×2^1
=(−1)(1)×(1+0.1110 0000 0000 0000 0000 000)×2^(128−127)
于是,符号位S=1,尾数M为1110 0000 0000 0000 0000 000阶码E为128=1000 00002,则最终的32位单精度浮点数为1 1110 0000 0000 0000 0000 000 1000 0000
3. 总结