float类型表示方式及范围深度解析

本文深入解析float类型的表示方式及其取值范围,包括符号位、指数位和尾数位的作用,介绍了最小与最大绝对值的计算方法,并通过示例代码验证理论分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        float类型的值以4个字节表示,共32bit,根据IEEE754标准,float类型使用1位做符号位,8位做指数位,23位做尾数位,格式如下:

在这里插入图片描述

整个浮点数可表示为:f = s \ast t \ast 2^{i} ,其中s为符号位-1或1,t为尾数,i为指数。

符号位
        0表示正,1表示负

指数部分
        指数位用8位移码表示。8bit可表示256个数,用移码可表示的十进制范围为-127~128。

  • 当指数位的移码为0表示浮点数的指数负无穷整个浮点数为0
  • 当指数位的移码为255时表示指数为正无穷浮点数为最大值

所以实际用来表示的移码范围为 1 ~ 254 ,转换成十进制原码为 -126 ~ 127,也就是整个指数部分(注意:只算指数部分)所能表示的最小的正数值为2^{-126} ,最大的值为2^{127} 。相当于用指数的8位对应的10进制是真实指数加上127得到的值。如图所示:

在这里插入图片描述

上图的解释:8位指数位的值为0,表示整个float值为0;8位指数位为255表示浮点数为无穷大inf。这俩是特殊情况,中间的254个值为一般情况。整个float的表征并不能用一个公式表示出来。也就是上面说的f = s \ast t \ast 2^{i}不能处理两种特殊情况。

 尾数部分
        尾数部分部分共23位,表示范围为0, 2^{23}-1。在规约式浮点数的尾数部分中小数点前还隐藏着一个固定的整数值整数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。那么整个数就是1.x*2^y。其中x为000 1111 11(后面的0没有用了),y为9。计算一下就是1.000 1111 11*2^9 =2^9*(1+0*2^{-1}+0*2^{-2}+0*2^{-3}+1*2^{-4}+1*2^{-5}+1*2^{-6}+1*2^{-7}+1*2^{-8}+1*2^{-9}) =512*(1+1/16+1/32+1/64+1/128+1/256+1/512) =575

  这里面的1.x其实是不严谨的,x用的是2进制序列。

最小绝对值分析
对于规约式浮点数可表示的最小的正数为 2^{-126} ,我们可用代码来验证:

 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的最小规约化正数为2^{-126}

 

当正数值小于 2^{-126} 时,指数部分将变成-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类型的数小于2^{-126} 次方时将不继续采用规约式表示,而改为非规约式表示,所谓非规约式表示也就是摆脱了小数点前必须为1的限制,对于小于2^{-126} 的数小数点前可以为0。

        采用渐进式下溢出的原因是,如果不采用,0与绝对值最小的浮点数之间距离将大于两个相邻浮点数之间的距离,且前者是后者的 2^{23} 倍!!!(绝对值最小的规约式浮点数之前计算出为2^{-126} ,与0的距离为2^{-126} ,倒数第二小的值为(1+2 ^{-23}) * 2^{ -126}=2^{ -126}+2^{ -149} ,与 2^{-126} 的距离为 2^{-149}。这两者之间差了2^{-23}倍。

        当采用了渐进式下溢出,float类型所能表示的绝对值最小的数便为: 2^{-149} ,(因为没有最前面的1以及带来的2^{-126})可用代码验证:

    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);
    }

运行结果为:

在这里插入图片描述

        当浮点数的绝对值小于2^{-149}时,则彻底超出了float所表示的最小绝对值,将会被表示成0。我们来验证一下2^{-150}

运行结果为:0.0

综上所述,float类型的最小绝对值数为:2^{-149}

最大绝对值分析
        最大绝对值就比较简单了,当尾数全为1,指数为127时为最大,也就是(2-2^{-23})* 2^{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表示范围

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值