zoukankan      html  css  js  c++  java
  • 浮点数存储格式学习:找到非规格数中最大和最小的数

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

    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

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

  • 相关阅读:
    B-Tree索引的学习记录
    mysql NOW,CURRENT_TIMESTAMP,SYSDATE 之间的区别
    哈希索引
    MyISAM和InnoDB的区别
    负载均衡记录一
    哈希索引
    mysql ZEROFILL属性
    redis常用命令及使用场景
    js Function()构造函数
    书写闭包的时候需注意一下情况
  • 原文地址:https://www.cnblogs.com/litifeng/p/10488908.html
Copyright © 2011-2022 走看看