zoukankan      html  css  js  c++  java
  • 计算机系统中的浮点数

    人类世界的小数的表示形式

    1、我们最习惯的小数表示形式是十进制,形式为:

      它的值为:

    2、小数的二进制表示法,形式为:

      它的值为:

    IEEE浮点标准

    在计算机系统中,因为有字节的限制(C语言中float类型占4字节,double类型占8字节),小数的表示要复杂的多。IEEE制定的浮点标准得到了所有的计算机的支持。

    IEEE浮点标准用如下形式表示一个数:
      符号(sign)s,1为负数,0为正数。数值0的符号位解释做特殊情况处理;
         尾数(significand 有效数)M是一个小数,范围为1~2-ε 或 0~1-ε (即 [1,2) 或 [0,1) ,详情请看“浮点数的类型”部分)
         阶码(exponent 指数)E的作用是对浮点数加权,这个权重是2的E次幂(可能是负数)
     
    标准浮点格式(浮点有3个字段组成)有以下两个类型:
      32位的单精度:s、exp和frac字段分别为1位、8位、23位
      64位的双精度:s、exp和frac字段分别为1位、11位、52位
     
     
    IEEE浮点数的类型
    依据阶码字段是否全为0、全为1分为以下三种:
    1、规格化的值:exp字段(阶码字段)的位模式不全为0,或不全为1.
      阶码E=e-Bias  其中,e是exp字段表示的无符号数,Bias是偏置值2^(k-1)-1(单精度为127,双精度为1023)。阶码E以此方式来表示成有符号数。因此得到E的范围:单精度-126~127,双精度-1022~1023
      若字段frac(尾数域)为  则定义尾数M=1+f,其中f=。即尾数域仅仅表示小数点后面的部分,隐含小数点前面为1。
     
    2、非规格化的值:当阶码字段全为0
      阶码E=1-Bias
      尾数M=f,不包含隐含的开头1
      目的是表示数值0;表示非常接近与0.0的数
     
    3、特殊值:阶码字段全为1
      当尾数域全为0,表示无穷大或无穷小
      当尾数域不全为0,结果值被称为NaN(Not a Number)
     
    我们用正数范围内的示例,来说明上面的三种类型的重大意义
      e:假定阶码字段是一个无符号整数表示的值
      E:偏置之后的阶码值
      2^E:阶码的权重数
      f:尾码字段描述的小数值
      M:尾数值
      V:小数值 V=2^E * M

    IEEE浮点表示的特点

    1,最大非规格化数7/512 到 最小规格化数8/512的平滑转变;
    2,若将上图中浮点数的位表达式解释为无符号整数,它们就是按升序排列的,就像它们表示的浮点数一样。(IEEE如此设计格式就是为了浮点数能够使用整数排序函数来进行排序)
    例如:
    typedef unsigned char *type_pointer;
    
    void show_types(type_pointer start,int len)
    {
        int i;
        for(i=0; i<len; i++)
            printf(" %.2x",start[i]);
        printf("\n");
    }
    
    int main()
    {
        float f1=1.0;
        show_types(&f1,sizeof(f1));
        return 0;
    }

    输出:00 00 80 3f

    分析:这个程序运行在windows 32位机上。window系统是小端法(数值的低字节放在内存的前端)机器。

    对于的二进制表示为:00111111 10000000 00000000 00000000

    float的第1位为符号位:0;第2至第9位为阶码位,供8位:E=127-127=0;后面的23位为尾码,M=1+0=1。

    所以,(-1)0*1*20=1.0

     
    浮点数的舍入方式
    IEEE浮点格式定义来四种不同的舍入方式。默认的舍入方式是:偶数舍入。
    偶数舍入(round-to-even):找最接近的数值,舍入到这个值;如果有两个可能的值,将数字向上或向下舍入,使得到的结果的最低有效数字是偶数。
    例如,将下面二进制舍入到小数后一位:
      11.001(2)->舍入:11.0(2)  11.0是最接近的数值
      10.010(2)->舍入:10.0(2)      10.0 和 10.1都是最接近的值,但是10.0的最低位为偶数
      10.110(2) ->舍入:11.0(2)      10.1 和 11.0 都是最接近的值,但是11.0的最低位为偶数
      
    浮点运算
    我们将x +y定义为Round(x + y),这是对实际运算的精确结果进行舍入后的结果。
    浮点加法的特点:
    1、浮点加法不具有结合性。(由于可能发生溢出,或者舍入而失去精度)
        float f1=(3.14+10000000000)-10000000000;
        float f2=3.14+(10000000000-10000000000);
        printf("%f %f ",f1,f2);

      输出:3.139999 3.140000

    2、浮点加法满足了单调性。
         无符号和补码加法不具有这个实数加法的属性(因为溢出的原因)
     
    必须非常小心地使用浮点运算,因为浮点运算只有有限的范围和精度,而且不遵守普遍的算术属性,比如结合性。
     
     
     
    不能表示 VS 不能精确表示

    在浮点数的表示范围内,有多于 99.999…% 的数在计算机中是不能表示的。从数量级分析一下,32bit 浮点数的表示范围是 10 的 38 次
    方,而表示个数呢,是 10 的 10 次方。 能够被表示的数只有 1/100000000…. (大概有30个零)。详细内容请见“代码之谜(五)- 浮点数(谁偷了你的精度?)

     
    (转载请注明出处 ^.^)
     
  • 相关阅读:
    jqgrid 获取选中用户的数据插入
    jqgrid 自定义文本框、选择框等查询
    Java学习—— for循环
    Android中 Http请求
    异步消息处理机制——Handler用法
    ThreadLocal
    Android开发 学习笔记——HelloWorld
    eclipse 常用插件
    mysql 命令备份还原
    学习
  • 原文地址:https://www.cnblogs.com/windlaughing/p/3006849.html
Copyright © 2011-2022 走看看