Java float和double存储结构
浮点数转换二进制
以18.725
为例进行说明。
整数部分转二进制:除2取余法。整数部分除以2取余数,商取整继续除以2取余数,直到商为0。
整数除法 | 商 | 余数 |
---|---|---|
$18/2$ | 9 | 0 |
$9/2$ | 4 | 1 |
$4/2$ | 2 | 0 |
$2/2$ | 1 | 0 |
$1/2$ | 0 | 1 |
18转换为二进制就是10010
,上面表格中余数的倒序。
小数部分转二进制:乘2取整法。小数部分乘以2,取整数部分,剩下的小数部分继续乘以2取整数部分,直到结果为0。如果永远不为零,则到达期望的精度后终止运算。
乘法公式 | 小数部分 | 整数部分 |
---|---|---|
$0.725*2=1.45$ | 0.45 | 1 |
$0.45*2=0.9$ | 0.9 | 0 |
$0.9*2=1.8$ | 0.8 | 1 |
$0.8*2=1.6$ | 0.6 | 1 |
$0.6*2=1.2$ | 0.2 | 1 |
$0.2*2=0.4$ | 0.4 | 0 |
$0.4*2=0.8$ | 0.8 | 0 |
$0.8*2=1.6$ | 0.6 | 1 |
$0.6*2=1.2$ | 0.2 | 1 |
$0.2*2=0.4$ | 0.4 | 0 |
…… | …… | …… |
0.725的二进制数是0.1011100110
(后面还有无限长,这里忽略)。所以18.725的二级制就是10010.1011100110
。按照规定,二进制小数点左边只能有1为且固定为1,所以需要进行右移操作,得出结果是:$1.00101011100110*2^4$
- 符号位:正数,符号位为0;
- 指数位:实际为4,按照规定要加上127(即指数最高位赋值为1),指数位存储的是131,二级制为
10000011
,。 - 底数位:取小数部分,即
0.00101011100110
;
为什么指数位要加上127呢?这是因为float类型指数位是8位,取值范围位-126~127,为了消除负数带来的实际计算上的影响(比如比较大小,加减法等),可以在实际存储的时候,给指数做一个简单的映射,加上一个偏移量,比如float的指数偏移量为 127,这样就不会有负数出现了。另外double类型是加上1024。
18.725存储的float二进制数据是:0 10000011 00101011100110...
。
可以通过下面代码进行验证:
1 | System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(18.725f))); |
字符串转浮点数
1 | //本示例是最基础的转换,比如输入“34.5789”,输出为 34.5789 |