作者: zengdongwu
转载地址: http://www.zengdongwu.com/article1.html
十进制科学记数法
98765 = 9.8765 * 104
尾数 基数指数
二进制科学记数法
1)1010 1011 = 1010 1011. * 20
2)1010 1011 = 1010 101.1 * 21
3)1010 1011 = 1010 10.11 * 210
4)1010 1011 = 1010 1.011 * 211
4)……
5)1010 1011 = 1.010 1011 * 2111
尾数 基数指数
小数点二进制科学记数法
101.0 1011(2) = 1.010 1011 * 210(2) = 5.34375(10)
二进制小数转十进制方法:
22 + 20 + 2-2 + 2-4 + 2-5 = 5.34375
十进制小数转二进制方法:
1)5.34375整数位为5,转二进制为101;
2)小数位0.34375 * 2 = 0.6875,整数位为0,结果101.0;
3)继续0.6875 * 2 = 1.375,整数位为1,结果101.01;
4)去掉整数继续乘2,0.375 * 2 = 0.75,结果101.010;
5)循环到没有小数为止……;
6)最终结果:101.01011。
float(32bit)二进制存储结构
0 | 1000 0001 | 0101 0110 0000 0000 0000 000 |
符号位 | 指数(8bit) | 尾数(23bit) |
原理说明:
1)第1位为符号位,0为整数,1为负数;
2)第2-9位为指数位,共8位,不足8位前面补0,由于指数没有符号位,不能表示负数,只能通过将结果减127来得到负数,所以指数位存储的结果是原指数加127,即指数2存储后指数为 2+127 = 129(10) = 1000 0001(2);
3)第10-32位为尾数位,共23位,不足23位后面补0,尾数位包含隐藏的1.X,即1.010 1011只存储0101 011,然后后面补0,最终结果为0101 0110 0000 0000 0000 000。
float转十进制方法:
1)符号位0为正数;
2)指数转十进制,1000 0001为129,需要减127,所以指数为129-127=2;
3)尾数去掉后面的0,结果为0101 011;
4)尾数前面加1. 即:1.010 1011;
5)指数为2,小数点往后移2位,即:101.0 1011;
6)转十进制22 + 20 + 2-2 + 2-4 + 2-5 = 5.34375。
代码验证:
float f = 5.34375f;
System.out.println(Integer.toBinaryString(Float.floatToIntBits(f)));
采用double(64bit)二进制表示方式
0 | 0010 0000 001 |
0101 0110 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 |
符号位 | 指数(11bit) | 尾数(52bit) |
原理说明:
1)第1位为符号位,0为整数,1为负数;
2)第2-12位为指数位,共11位,不足11位前面补0,由于指数没有符号位,不能表示负数,只能通过将结果减1023来得到负数,所以指数位存储的结果是原指数加1023,即指数2存储后指数为 2+1023 = 1025(10) = 10000000 1(2);
3)第13-64位为尾数位,共52位,不足23位后面补0,尾数位包含隐藏的1.X,即1.0101011只存储0101011,然后后面补0,最终结果为0101 0110 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000。
double转十进制方法:
1)符号位0为正数;
2)指数转十进制,1000 0000 001为1025,需要减1023,所以指数为1025-1023=2;
3)尾数去掉后面的0,结果为0101 011;
4)尾数前面加1. 即:1.010 1011;
5)指数为2,小数点往后移2位,即:101.0 1011;
6)转十进制22 + 20 + 2-2 + 2-4 + 2-5 = 5.34375。
代码验证:
double d = 5.34375;
System.out.println(Long.toBinaryString(Double.doubleToLongBits(d)));
PS:double转换方法与float一致,区别在指数位算法有所差异,且尾数大小远远超过了float,因此精度也大大提高,正常情况下浮点数均采用double。