小数二进制的转换和浮点数的存储是两个不太相关的内容,所以本文分两个主题分别记录。
进制转换
十进制整数转二进制
除二取余法,余数倒排。
原理来源于:
十进制:
二进制:
反向求解的时候就是除2(基数)取余。
11 ÷ 2 = 5 余 1
5 ÷ 2 = 2 余 1
2 ÷ 2 = 1 余 0
1 ÷ 2 = 0 余 1
得到二进制:1011
十进制小数转二进制
乘二取整。
原理来源于:
十进制:
二进制:
反向求解的时候就是乘2(基数)取整:
0.6825 * 2 = 1.375 拿走整数部分1,剩0.375
0.375 * 2 = 0.75 拿走整数部分0,剩0.75
0.75 * 2 = 1.5 拿走整数部分1,剩0.5
0.5 * 2 = 1 拿走整数部分1,剩0,结束
得到二进制:0.1011
通过上面的运算可以知道:11.6825转成二进制是:1011.1011
另外一个规律:小数尾数为5(x.5、x.25、x.xxxxx5)才能用完整的二进制表示,不然一直乘2小数部分永远不能为0。
快速运算:
0.1(二进制)=0.5(十进制)
0.01(二进制)=0.25(十进制)
0.001(二进制)=0.125(十进制)
……
小数存储
我们假设,小数点存储在中间,假设用8bit来存储小数:
1011 1011
就等于1011.1011。用16bit来存储小数:0000 1011 1011 0000
就等于1011.1011。
以上只是我们的假设,为了统一,现在计算机都采用IEEE 754的标准来存储小数(浮点数)。有单精度(32bit)和双精度(64bit)两种。
统一公式:
其中s为符号位,E为阶码,M为尾数。
s为所见即所得,0正数,1负数。
E为移码表示,移,相当于加上,Bias称偏移量。
M为尾数,隐藏最高位1,相当于计算尾数时,要加上1。
以0.4375为例,因为M尾数最高位要为1,也就是我们要想办法让0.4375表示成的形式:
用单精度表示,偏移量为:
现在的任务变成了将125和1.75(需要隐藏高位1,变成0.75)转换成二进制:
、
所以0.4375的浮点数表示就是:
在线转换网址
同理,将 转换成小数就是:
阶数:0111 1101 = 125,实际 125 - 127(偏移量) = -2
尾数:1100 0000 0000 0000 000 = 0.11(二进制) = 0.5+0.25=0.75(十进制)
尾数补隐藏位1:1+0.75=1.75
原小数:
双精度浮点数的偏移量:
利用java转换
long l = Double.doubleToLongBits(0.4375);
System.out.println(l);
// 11111111011100000000000000000000000000000000000000000000000000
System.out.println(Long.toBinaryString(l));
Long aLong = Long.valueOf("11111111011100000000000000000000000000000000000000000000000000", 2);
double v = Double.longBitsToDouble(aLong);
// 0.4375
System.out.println(v);
网友评论