• 浮点数存储格式学习:找到非规格数中最大和最小的数


    在学习《深入理解计算机系统》的浮点数存储里,我想到一个问题,单精度浮点数中,非规格浮点数最大数是几?

    00000000011111111111111111111111

    符号位:0

    指数域:00000000

    小数域:11111111111111111111111

    指数域全0,小数域全1,符号位0,这个数应该是非规格数中最大的一个了,那么这个数存在吗?计算机是这样存储的吗?

    单精度浮点数:符号位1个,指数位8个,小数位23个,偏置值bias=127,E=1-bias=-126,M=f=(0.11111111111111111111111)2

    根据存储定义:浮点数V=(-1)sM2E,V=(0.11111111111111111111111)2 * 2-126

    让我们开始编程查看一下吧:

    #include <cstdio>
    int main(){
        float a=0.5,c=0.5;
    //第一个for是将a的值累加到(0.111...11),注意0.5在二进制下就是0.1
    for(int i=0;i<22;i++){ c*=0.5; a=a+c; }
    //第二个for将a和2-126相乘。
    for(int i=0;i<126;i++){ a*=0.5; } unsigned int b=*(int *)&a; for(int i=0;i<32;i++){ printf("%d",(b>>(31-i))&1?1:0); } printf(" b=%d ",b); return 0; }

    输出:

    vagrant@ubuntu-bionic:~$ ./t
    00000000011111111111111111111111
    b=8388607     //震惊,连b的值都有意义了,8388607=223-1

    解释:第一个for中,将循环次数设为22,是因为a本身有一个1,只需再加22个就够了。更有意思的是:如果把次数改为23,则全0,也就是浮点数的0了,如果改为24,那么就是规格数中最小的一个喽,呵呵,有意思,终于理解《深解》说的平滑过渡啥意思了。

    那么这个最大的非规格浮点数到底是多少呢?在上面程序加上一句:

    printf("%.200f
    ",a);

    输出:

    vagrant@ubuntu-bionic:~$ ./t
    00000000011111111111111111111111
    a=0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875000000000000000000000000000000000000000000000000000

    最后面的0可以删除,这样是为了看着方面,确认没数了。这个数最大的非规格浮点数是:

    a=0.00000000000000000000000000000000000001175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875

    数字前面有37个0,a*1038约等于1.1755,这还是非规格数里面最大的一个,晕。

    那么最小的非规格数是多少呢?基本和前面同理:

    #include <cstdio>
    int main(){
        float a=0.5;
        for(int i=0;i<22;i++){
            a*=0.5;
        }
        for(int i=0;i<126;i++){
            a*=0.5;
        }
        unsigned int b=*(int *)&a;
        for(int i=0;i<32;i++){
            printf("%d",(b>>(31-i))&1?1:0);
        }
        printf("
    a=%.200f
    ",a);
        printf("
    b=%d
    ",b);
        return 0;
    }

    输出:

    vagrant@ubuntu-bionic:~$ ./t1
    00000000000000000000000000000001
    a=0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125000000000000000000000000000000000000000000000000000
    
    b=1

    这就是浮点数,如果你懂它,它也很精确的。

  • 相关阅读:
    [POJ 2777]Count Color 线段树+二进制状态压缩
    [git] git push问题 解决 Updates were rejected because the tip of your current branch is behind 和每次输入用户名和密码
    [hdu-5795]A Simple Nim 博弈 尼姆博弈 SG函数打表找规律
    [codeforces1284E]New Year and Castle Construction 几何
    Spring事务相关接口以及实现类
    MyBatis与Spring整合
    实现一个简易RPC
    使用CAS实现一个超时锁
    阻塞队列
    Java中的Lock接口
  • 原文地址:https://www.cnblogs.com/litifeng/p/10488908.html
Copyright © 2020-2023  润新知