1、浮点数的表示格式
1.1、十进制格式
0.00172=1.72*10^-3,1.72为系数(或尾数),10^-3为指数,10为指数的基数,-3位为指数的阶数。科学计数法表示为1.72E-3,由于1<=1.72<10,因此称系数是规格化的。
1.2、二进制格式
比如19.625,整数部分19的二进制为10011,而小数部分0.625的二进制为101,则总体表示为10011.101,科学计数法表示为1.0011101*2^4
因为小数点后第一位为2^-1,小数点后第二位为2^-2,依次类推。那么0.625=0.5*1+0.25*0+0.125*1=101。
2、浮点数的存储
IEEE 标准754将浮点数的存储分三个部分:
- 符号位
- 指数位
- 有效数字(系数位)
单精度浮点数32位=1位符号位+8位指数位+23位有效数字
双精度浮点数64位=1位符号位+11位指数位+52位有效数字
下面以单精度浮点数为例(双精度同理),来看看计算机是如何存储的。
- 符号位:1表示负值,0表示正值;
- 指数位:阶数的二进制码,是一个无符号的整数,但是阶数既可以是正数也可以是负数,那么就需要有一个偏移量(单精度偏移量为127,双精度偏移量为1023),则真正的阶数=移码指数-偏移量。指数位的范围为0~255,但不包括0和255,因为它俩有特殊含意(这个下面会讲到),因此单精度浮点数可表示的最大阶数为127=254-127,最小阶数为-126=1-127;
- 有效数字:任何一个二进制的科学计数法(规格化)的系数第一位都是1,因此这个1没有必要存储,有效数字存储的都是小数点后23位,因此23位有效数字可表示的精度却是24位;
2.1、指数0和255的特殊用途?
符号位s | 指数位e | 有效数位m | 浮点数 |
---|---|---|---|
0、1 | 0 | 0 | 0 |
0、1 | 0 | !=0 | 0.0f |
0 | 255 | 0 | 无穷大 |
1 | 255 | 0 | 无穷小 |
0、1 | 255 | !=0 | NAN |
2.1、单精度的最大最小值?
注意:最小值不考虑符号,即系数+指数能表示的最小值;
首先,用Java代码打印出单精度的最大值和最小值。
// 3.4028235E38
System.out.println(Float.MAX_VALUE);
// 不受限制的最小值,1.4E-45
System.out.println(Float.MIN_VALUE);
// 规格化的最小值,1.17549435E-38
System.out.println(Float.MIN_NORMAL);
如何求出最大值?
- 使系数的23位全为1,则系数为2-(1/2^23),约等于2,指数最大为127,则单精度最大值为约等于2*2^127=2^128,即可得出。
如何求出规格化的最小值?
- 规格化的意思是,系数的前面必须有个1。那么使系数全为0,则系数为1,指数最小为-126,则规格化的单精度最小值为2^-126,即可得出。
如何求出不受限制的最小值?
- 如果不受限制,即不是规格化的,则系数最小可表示2^-23,指数最小为-126,则不受限制的单精度最小值为2^-23*2^-126=2^-149,即可得出。
2.2、计算机为什么会出现精度丢失问题?
精度丢失的原因如下:
- 小数的二进制无法精确地表示,但是整数可以
- 单精度和双精度类型混合使用
// 0.8999999999999999
System.out.println(2-1.1);
如上面代码所示,用Java打印出2-1.1的结果,然后结果却不是0.9,这是因为0.9的二进制计算机无法表示,下面来做一下演示。
0.9 * 2 1(结果是1.8,取整数部分1)
0.8(结果是1.8,取小数部分0.8继续运算) * 2 1
0.6 * 2 1
0.2 * 2 0
0.4 * 2 0
0.8 * 2 1
0.6
计算到这里大家就能看出来了,出现了循环,因此0.9的二进制是表示不出来的。
2.3、浮点数和定点数的区别是什么?
浮点数的意思是小数点可以变动,在计算机中是依赖指数来实现的。比如56.78*10^0 = 5.678*10^1 = 567.8*10^-1,它们的大小相同,区别是小数点的位置不同,指数的大小也不同;
而定点数,顾名思义就是小数点不能变动。例如Mysql中的decimal类型。