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

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

  • 相关阅读:
    POJ 1003 解题报告
    POJ 1004 解题报告
    POJ-1002 解题报告
    vi--文本编辑常用快捷键之光标移动
    常用图表工具
    September 05th 2017 Week 36th Tuesday
    September 04th 2017 Week 36th Monday
    September 03rd 2017 Week 36th Sunday
    September 02nd 2017 Week 35th Saturday
    September 01st 2017 Week 35th Friday
  • 原文地址:https://www.cnblogs.com/litifeng/p/10488908.html
Copyright © 2011-2022 走看看