• 浮点数在计算机中的表示



    接上一篇博客《为什么会有补码?》,我仅仅分析了整数在计算机中表示方式,但是计算机中的浮点数又是如何表示的呢?

    引子

    首先,使用之前博客的程序,可以看到如下的这些实数在计算机中的计算结果是

    实际数值 数值类型 计算机中的表示
    102.3235 float 42CCA5A2
    -3.256 float C050624E
    120.254 double 405E104189374BC7
    -56.2441 double C04C1F3EAB367A10

    右边的计算机中的数值表示是按照《IEEE 754-2008》的标准存储数据的,具体的规定如下所示。

    IEEE 754 标准

    表示形式

    IEEE 754 规定了二进制浮点数在计算中的存储方式,我们以 C 语言中的 float 为例来具体说明。无论是 32 位系统还是 64 位系统,计算机中的 float 占用 4 个字节,我们就使用这些字节来存储任意的浮点数,可以参考下图

    转化成对应的数学表示形式,浮点数 V

    [V = (-1)^s imes M imes 2^E ]

    • s表示符号位,占据 1 个 bit 位,如果是负数则 s=1s=1,如果是非负数则 s=0;
    • M表示 mantissa,占据 23 个比特,表示有效数字,表示的数字介于 1 和 2 之间;
    • E为非负整数,表示基于 2 为基数的指数大小,占据 8 个比特。

    因此,如果确认了上面 3 个参数,也就唯一确定了浮点数在计算机中的存储形式。我们以102.3235为例,来看看上面的这几个数字是如何表示出来的?

    1. 102.3235的二进制原码形式是1100110.01010010110100001110 = 1.10011001010010110100001110*2^6
    2. 确认 s。因为是正数,因此 s=0。
    3. 确认 M。M 表示1.xxxxxx之后的xxxxxx的部分,即计算机内部保存M时,默认表示的第一位总是1,可以舍弃表示1的这一位,而仅仅存储小数点之后的部分。因此 M=10011001010010110100001110,因为只能存储23个比特,将多余的位数部分截断得到 M=10011001010010110100001。
    4. 确认 E。它是个非负整数,按照第 1 步计算出来的结果,我们的指数应该是 6。但是,IEEE 规定根据二进制计算浮点数时,需要给指数减去一个偏置值,对于 float 类型这个数为 127,对于 double 类型,这个数是 1023。因此反过来,在将数字转换成二进制存储的时候,要加上这个偏置值,因此 E=6+127=133。
    5. 综合以上的所有计算结果,最后在计算机中存储的形式是01000010110011001010010110100001,转换成 16 进制就是42CCA5A2

    特别规定

    依照上面的方法,可以依次确认其他 3 个浮点数的表示形式。这都是比较常规的规格化数据的处理方法,IEEE 针对一些特殊的数字(绝对值特别接近 0 的数字或者无穷大无穷小),引入了一些特殊的规定,称为非规格化表示方法,总结如下。

    • 规格化数据。如果指数部分既不是 0 也不是 255(EE 不全为 0 或者不全为 1),就是规格化存储方式,具体的计算方法与之前介绍的相同。
    • 非规格化数据。E全为0 就是非规格化的数据,此时的指数固定为 1-127 或者 1-1023,有效数字 MM 的计算不再舍弃第一位的 1,而是 0.xxxxxxxx 的小数部分,这样就可以表示 0 和非常接近 0 的小数字。需要注意的是,0 有两种表示。
    • 特殊数字。E全为1 表示特殊的数字
      • 如果M全为 0,表示无穷大,正负取决于符号s;
      • 如果M不全为 0,表示这是一个非数 NaN(Not a Number)。

    精度误差及表示范围

    如果明白之前的内容,那就可以计算出来每种表示方法的取值范围以及表示的数据误差。在计算之前,有如下的一些假设:

    1. 正数和负数的表示方法是对称的,因此我们仅仅关注正数即可;
    2. 不考虑特殊值的计算,因为其仅仅是计算了不同几个数值,没有计算的价值。

    如果需要计算最大的规格化数字,那么其在内存中的表示应该是 s=1,M=1.11…1,E=111…10,最后的结果就是 1.1111…1×2127=3.4×1038,其他的基本可以推测出来了,如下表所示

    参考资料

  • 相关阅读:
    idea中yml文件变成text样式并且没有提示
    挂载redhat镜像创建本地yum源
    Windows环境下Oracle数据库的自动备份脚本
    Oracle存储过程锁表
    DDL和客户端ip监控
    Linux 单实例oracle安装步骤
    Linux常用命令
    Linux常用目录
    oracle基础知识及语法
    Linux下Oracle新建用户并且将已有的数据dmp文件导入到新建的用户下的操作流程
  • 原文地址:https://www.cnblogs.com/bugxch/p/14190977.html
Copyright © 2020-2023  润新知