float类型的值以4个字节表示,共32bit,根据IEEE754标准,float类型使用1位做符号位,8位做指数位,23位做尾数位,格式如下:
整个浮点数可表示为:
,其中s为符号位-1或1,t为尾数,i为指数。
符号位
0表示正,1表示负
指数部分
指数位用8位移码表示。8bit可表示256个数,用移码可表示的十进制范围为-127~128。
- 当指数位的移码为0表示浮点数的指数为负无穷,整个浮点数为0;
- 当指数位的移码为255时表示指数为正无穷,浮点数为最大值。
所以实际用来表示的移码范围为 1 ~ 254 ,转换成十进制原码为 -126 ~ 127,也就是整个指数部分(注意:只算指数部分)所能表示的最小的正数值为
,最大的值为
。相当于用指数的8位对应的10进制是真实指数加上127得到的值。如图所示:

上图的解释:8位指数位的值为0,表示整个float值为0;8位指数位为255表示浮点数为无穷大inf。这俩是特殊情况,中间的254个值为一般情况。整个float的表征并不能用一个公式表示出来。也就是上面说的
不能处理两种特殊情况。
尾数部分
尾数部分部分共23位,表示范围为
。在规约式浮点数的尾数部分中小数点前还隐藏着一个固定的整数值整数1,尾数部分的23位只用来表示小数点后的值,这种方式可保证浮点数有唯一的表示形式。规约式浮点数尾数部分如图所示:

以575.00000为例。其对应的4个字节从低到高依次为00 c0 0f 44。我们将它转换成2进制来看,从高到低依次是0100 0100 0000 1111 1100 0000 0000 0000,其中符号位为最高位0,表示正数。指数位为100 0100 0,为128+8=136。尾数为000 1111 1100 0000 0000 0000。那么整个数就是
。其中x为000 1111 11(后面的0没有用了),y为9。计算一下就是
这里面的1.x其实是不严谨的,x用的是2进制序列。
最小绝对值分析
对于规约式浮点数可表示的最小的正数为
,我们可用代码来验证:
public static void main(final String[] args) throws InterruptedException { BigDecimal b1 = new BigDecimal("0.5"); System.out.println(b1.pow(126).floatValue()); //2的-126次方的浮点数值 System.out.println(Float.MIN_NORMAL);//浮点数的最小规格化正数 }
讯享网
输出结果表明float的最小规约化正数为
:

当正数值小于
时,指数部分将变成-127,根据前面的指数部分的介绍,此时的浮点数应为0,我们使用代码来验证发现并不是0:
讯享网 public static void main(final String[] args) throws InterruptedException { BigDecimal b1 = new BigDecimal("0.5"); System.out.println(b1.pow(126).floatValue()); System.out.println(b1.pow(127).floatValue()); }
运行截图:

这是因为float类型采用了渐进式下溢出,当float类型的数小于
次方时将不继续采用规约式表示,而改为非规约式表示,所谓非规约式表示也就是摆脱了小数点前必须为1的限制,对于小于
的数小数点前可以为0。
采用渐进式下溢出的原因是,如果不采用,0与绝对值最小的浮点数之间距离将大于两个相邻浮点数之间的距离,且前者是后者的
倍!!!(绝对值最小的规约式浮点数之前计算出为
,与0的距离为
,倒数第二小的值为
,与
的距离为
。这两者之间差了
倍。
当采用了渐进式下溢出,float类型所能表示的绝对值最小的数便为:
,(因为没有最前面的1以及带来的
)可用代码验证:
public static void main(final String[] args) throws InterruptedException { BigDecimal b1 = new BigDecimal("0.5"); System.out.println(b1.pow(149).floatValue()); System.out.println(Float.MIN_VALUE); }
运行结果为:

当浮点数的绝对值小于
时,则彻底超出了float所表示的最小绝对值,将会被表示成0。我们来验证一下
运行结果为:0.0
综上所述,float类型的最小绝对值数为:
最大绝对值分析
最大绝对值就比较简单了,当尾数全为1,指数为127时为最大,也就是
使用代码来验证下:
讯享网 public static void main(final String[] args) throws InterruptedException { BigDecimal b1 = new BigDecimal("2"); System.out.println(b1.pow(128).subtract(b1.pow(104)).floatValue()); System.out.println(Float.MAX_VALUE); }
运行结果如下:
原文:float类型表示方式及范围深度解析_lcdxshengpeng的博客-CSDN博客_float表示范围
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/44818.html