标签:
浮点数,顾名思义,小数点能在数据中左右移动的数据,有单精度(float)和双精度(double)之分
基本表示方式:V = (-1)^S * M * 2^E
S:符号位,0表示正数,1表示负数
M:尾数,小数点后的数,小数点前面默认为1,这样可以省出一个二进制位
E:指数,又称阶码
根据IEEE754标准,单精度和双精度位数分配如下
float:1位符号位, 8位指数, 23位尾数
double:1位符号位, 11位指数, 52位尾数
以上说明有时候会让人很晕,一个是表示方式,一个是标准规定,怎么结合在一起呢,下面就以float来说明各个位数分配的意义以及分析最大值、最小值、精度等是怎么确定的。
1. 符号位
以最高位来区分一个数是正数还是负数,1表示负数,0表示正数
2. 指数
可能有的人很随意的按照补码的规则确定其大小范围,比如8位二进制,能够表示的范围为-128~127,而这里float的指数位正好为8位,就认为指数取值范围为-128~127,这是错误的。
首先,指数没有符号位,最高位不是非符号位,那么8位所能表示范围为0~255。
其次,根据IEEE754标准,指数为0和255有特殊含义(在最后说明),因此8位所能表示范围为1~254。但是根据科学表示法计算出来只能表示大于1或小于-1的数,那无限趋近0的数该怎么表示呢,因此需要一个数来平衡指数的取值范围,这个数就是偏差值,偏差值是通过2^(e - 1) - 1计算得到的,比如这里8位指数,那么偏差值为2^(8 - 1) - 1 = 127,将指数减去这个偏差值得到指数最终的取值范围-126~127
3. 尾数
尾数,即小数点后的数,尾数也没有符号位,比如这里float有23位尾数,2^23 - 1= 8388608,则尾数的值范围为0~8388608,那么加上小数点前的1构成的小数范围为1.0~2(趋近于2)。另外小数点后0到8388608的有效值都能保证精度,但是超过了这个范围就无法保证精度,会产生精度丢失,比如8388609就无法保证精度,这时就要使用双精度来表示。因此float的有效小数位为6~7位,因为第7位无法完全保证精度。
4. 总结
根据上面分析,得出
float的最大值为1 * 2 * 2^127 = 3.40 * 10^38,这个和Float.MAX_VALUE输出结果一致
float的最小值为1 * 1.0 * 2^(-126) = 1.175 * 10^(-38),这个和Float.MIN_NORMAL输出结果一致
注:上面的指数是依据规范化标准得出的,还有一种非规范化标准,可以让最小值更小(可以达到1.4 * 10^(-45),和Float.MIN_VALUE输出一致),这里就不做分析,参考IEEE754标准,总结计算得出如下表
浮点类型 | 最大值 | 规格最小值 | 非规格最小值 | 指数范围 | 有效小数位 |
Float | 3.4E38 | 1.175E-38 | 1.4E-45 | -126~127 | 6~7 |
Double | 1.80E308 | 2.225E-308 | 4.9E-324 | -1022~1023 | 15~16 |
5. IEEE754特殊规定
指数为0,尾数为0,则该数为0,比如前面提到的指数为0的情况
指数为2^e -1,尾数为0,则该数无穷大,比如前面提到指数为255的情况
指数为2^e -1,尾数非0,则该数不是一个数
标签:
原文地址:http://www.cnblogs.com/windyrain/p/5756770.html