zoukankan      html  css  js  c++  java
  • IEEE浮点数float、double的存储结构

    众所周知,C的float、VB的Single都是32位浮点数变量类型(也叫单精度浮点数),C的double和VB的Double则都是64位的浮点数变量类型(也叫双精度浮点数)。有些编译器还支持更屌的long double(貌似是80位还是128位的我不清楚,总之存在这种变态玩意儿。)那么这些浮点数从最底层的角度来看,它们是怎么存储的呢?我来举个例子解释下。计算机用的是二进制,如果我用二进制跟大家解释大家可能觉得看不懂,那我就用十进制来跟大家解释。
    浮点数分三个部分,第一个部分是有效数字,第二个部分给出小数点的位置,第三个部分用来判断这个数是正数还是负数。举例如下:
    浮点数123.456
    那么它用浮点数的存储格式来表示就是:有效数字就是123456,小数点的位置在3的后面,然后它是正数。

    那么我们要做的就是先取出有效数字123456,然后在3的后面插入小数点.就成了123.456,最后给它加个正号,就是+123.456了。

    从二进制的方面来理解也是一样的,比如我要表示-10101010.01010101,那么它的有效数字是1010101001010101,小数点在中间,然后它是负数。
    上面我都只说了“小数点在中间”、“小数点在3后面”这种比较含糊的表达方法。那么浮点数到底是怎么存储小数点的位置呢?这里我们要注意一整个浮点数中用来表示小数点位置的位数是多少。
    还是用十进制来给大家举个例子。假设我用两个位来表示小数点的位置,那么两个十进制位表示的最小的数是00,最大的数是99,我们总共能表达100个值。假设我要表达1234.5678,那么情况就是如下所示的:
    有效数字是12345678
    小数点的位置在中间。
    这里我们用两个十进制位来表示小数点的位置,那么这个小数点从左往右数(原来的数字是1234.5678)是在第四个位的后面。因此这两个十进制位的值就是03。因为00表示从左往右数的第一个位的后面,01表示从左往右数的第二个位的后面,02表示从左往右数的第三个位的后面,那么03就表示从左往右数的第四个位的后面了。
    有人可能会说“但是这样一来我们不就无法表现小数了嘛。”其实不然。比如我们要表现0.233,那么我们就把有效数字设置成“0233”,然后小数点位置是00就行了。
    对应的,二进制表示也是这样的,比如我们用8个二进制位来表示小数点的位置,我们要表现的小数是10101010.01010101,那么小数点在从左往右数第八个位的后面,我们就用00001000来表示小数点的位置。

    这里我就需要针对性地告诉大家,float和double是怎么回事。
    float浮点数的有效数字是23位,小数点用8个位表示,然后符号(正、负)用一个位表示(0表示正、1表示负),总共组成32位。
    因为float浮点数用8个位表示小数点的位置,因此小数点可以有256个位置。float浮点数规定从左往右数第127位的值必须是1,然后从第128位开始才是float的23位有效数字。因此float的浮点数的23位有效数字其实是从左往右数从第128位开始的。
    我这里举个例子:浮点数1.0f是怎么存储的:
    0 01111111 00000000000000000000000(0x3F800000)
    其中蓝色的部分是符号位,0表示正数。
    黄色的部分表示小数点的位置,在从左往右数第127位处。
    绿色部分是有效数字,共23个0,也就是全零。如果转换为十进制,大约就是6、7个数位左右。
    按照float浮点数的特性,第127位的值必须是1,然后存储的23位有效数字的位置是在第128位开始的,我们把这个浮点数展开为256位,是这样表示的:
    000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    前面的那些零和后面的那些零都是“虚构的”,也就是说这些零并没有被存储在float里面,而是同于补充位数的。第127位被强制设置为“1”,这是float的规定。
    浮点数存储了它的小数点位置:01111111,也就是“127”这里。那么我们最终得到的浮点数是:1.0

    同样的,double也是和float一样用三个部分表示浮点数:有效数字,小数点位置,符号。
    double的有效数字是52位,小数点位置用11个位表示,符号位用一个位表示。十进制可以精确到16个数位左右。
    我这里举个例子:浮点数1.0是怎么存储的:
    0 01111111111 0000000000000000000000000000000000000000000000000000(0x3FF0000000000000)
    其中蓝色的部分是符号位,0表示正数。
    黄色的部分表示小数点的位置,在从左往右数第1023位处。
    绿色部分是有效数字,共52个0,也就是全零。
    按照double浮点数的特性,第1023位的值必须是1,然后存储的52位有效数字的位置是在第1024位开始的,我们把这个浮点数展开为2048位,是这样表示的:
    00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    在这2048位的数字中,我们的double存储的52个有效数字在其中的绿色部分,也就是从1024位开始处。1023位被强制设置为1。可以看出,double的精度比起float提高了不少。
    小数点的位置:01111111111表示小数点在第1023位的后面,因此最终得到的浮点数的数值是1.0

    除了float和double,还有其它格式的浮点数:
    Minifloat:迷你浮点数(8位):
    1位符号位,4位小数点位置,3位有效数字。(PS.真够“迷你”的)
    Half:半精度(16位):
    1位符号位,5位小数点位置,10位有效数字。
    x86 Extended Precision Format:x86扩展精度格式(80位):
    1位符号位,15位小数点位置,1位特殊位,63位有效数字。特殊位请看http://en.wikipedia.org/wiki/Extended_precision
    Quadruple:四倍精度(128位):
    1位符号位,15位小数点位置,112位有效数字。

    IEEE规定:
    1、表示小数点位置的部分如果全零,那么这个浮点数的值为0,而如果这个时候有效数字部分非零,那么这个浮点数就“不是一个数”(NaN)
    2、表示小数点位置的部分如果全一,那么这个浮点数的值为无穷大。
    3、浮点数能表示的最大数值:表示小数点位置的部分除了最低位为零其它均为一,有效数字全为1
    4、浮点数能表示的最小数值:表示小数点位置的部分除了最低位为一其它均为零,有效数字全为0

    参考资料
    http://en.wikipedia.org/wiki/Minifloat
    http://en.wikipedia.org/wiki/Half-precision_floating-point_format
    http://en.wikipedia.org/wiki/Sin ... oating-point_format
    http://en.wikipedia.org/wiki/Dou ... oating-point_format
    http://en.wikipedia.org/wiki/Extended_precision
    http://en.wikipedia.org/wiki/Qua ... oating-point_format

    https://www.0xaa55.com/forum.php?mod=viewthread&tid=462

  • 相关阅读:
    java 8新特性 匿名内部类的使用
    java 8新特性
    jmeter 性能测试
    idea 背景颜色设置
    SpringBoot yaml的配置及使用
    idea 类图显示
    SpringSecurity 获取认证信息 和 认证实现
    MySQL-慢查询日志
    微信小程序领取卡券
    ThinkPhp5-PHPExcel导出|导入 数据
  • 原文地址:https://www.cnblogs.com/findumars/p/5557203.html
Copyright © 2011-2022 走看看