二进制怎么表示浮点数?
按照2进制,浮点数据可以这么算
4.5 = 100.1
有的同学可能会问了,100我明白,代表着4,那么小数点后面的那个1为什么能代表0.5?
其实是这么算的,小数点后面的表达式是1/2^n
小数点后面是1 ,那么2的1次方就是2,1/2 = 0.5了。
那么反过来100.01就等于4.25,100.11的0.11 = 0.1 + 0.01 等于0.5 + 0.25 = 4.75
二进制表示浮点数的规范
按十进制来说,550 = 5.5 * 10^2
那么二进制的浮点也可以这样表示
4.5 = 100.1 = 1.001 * 2^2
此时尾数是1.001 ,指数是2.
方程大概如下,但这块不建议你现在看,而是等看完所有章节了再回头看这个方程。
d.dd...d × βe , (0 ≤ di < β)
其中 d0.dd...d 即尾数,β 为基数,e 为指数。尾数中数字的个数称为精度,每个数字 d 介于 0 和基数β之间,包括 0。小数点左侧的数字不为 0。在二进制里,β=2
我们发现,所有的浮点数都可以表示为1.xxxx *2^N,x只能表示0和1(或许你有其他疑问,但请暂时完全相信这一点,后面我会专门写一章来解释)
因此,在实际存储中,我们会省略掉最前面的1,直接拿到小数点后面的当作尾数。
那么在计算机里存储就大概是这样的,下面是个float类型的存储
+- | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
float一共32位。
其中第一位是符号位,2~9符号位位是指数位,后面的是尾数位。
我们来测试一下,边看现象,边说明:
public class Test1 {
public static void main(String[] args) {
System.out.println("01234567812345678123456781234567");
p(Integer.toBinaryString(Float.floatToIntBits(4.5f)));//1/2~1
p(Integer.toBinaryString(Float.floatToIntBits(4.75f)));//1/2~1
p(Integer.toBinaryString(Float.floatToIntBits(4.25f)));//1/2~2
p(Integer.toBinaryString(Float.floatToIntBits(4.125f)));//1/2~3
}
private static void p(String binaryString) {
int l = 32 - binaryString.length();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < l; i++) {
sb.append("0");
}
StringBuffer append = sb.append(binaryString);
String string = append.toString();
System.out.println(string);
}
}
打印结果:
0 12345678 12345678 12345678 1234567
0 10000001 00100000 00000000 0000000
0 10000001 00110000 00000000 0000000
0 10000001 00010000 00000000 0000000
0 10000001 00001000 00000000 0000000
说明:
1.最上面打印的01234567812345678123456781234567是为了好观察位数。我们把第一位设置为0,紧挨着的后面8个就是指数,然后再后面的就是尾数。
2.Float.floatToIntBits方法会按float的bit排序生产一个int数。
比如:4.5f的二进制bit排序时0 10000001 00100000 00000000 0000000,那么它就生成一个int数,也是这个排序。
3.Integer.toBinaryString是按二进制打印int数,比如8打印出1000,但由于这个方法会自动忽略前缀所有的0,所以这里写了一个p方法,自动补全到32位,不足长度的在前面补0.
4.前面的指数不看,指数是根反码补码有关的,有兴趣的同学可以了解一下。
5.我们推测4.5 = 100.1 = 1.001 * 2^2。由于舍掉了效数点前面的1,所以尾数应该是001。观察4.5f的尾数,发现正是001
至于指数是2,需要根据反码补码来计算出来,也正是2
6.推测4.75= 100.11 = 1.0011 *2^2,尾数0011也是符合的,进而你可以推断4.125和4.25。
这些是最为简单的,告诉你浮点型是怎么存储的,接下来,我们更进一步,来看看浮点型为什么不准确。