zoukankan      html  css  js  c++  java
  • C浮点数据格式

    #include <stdio.h>

    int main(int argc, char *argv[])
    {
        float p = 5.1f;
        int f = (int)(p*100);
        printf("%d", f);
        getch( );
        return 0;
    }

    我想要输出 510,可是机器nnd居然输出509(竟然敢扣我工钱)。
    到底是what's wrong。我上看下看,左看又看,看了又看,就是发现不了错误。
    于是我试着把5.1改成5.5,一切正常啊。捣鼓了N个小时后猜想,莫非是浮点数的表示问题,
    于是花了很久找到浮点数的机器表示方法,照着规定克隆操作了一下。(据说练过乾坤大
    挪移的人什么招式都可以克隆)。

    IEEE规定的浮点数的机器表示:

    32位机器的 float 是4字节的,共32位。
    第1位是符号位,接着8位指数位,接着23位基数位。
    以5.1为例。

    5 = 101 (2进制)

    0.1 = 0.0 0011 0011 0011 0011 0011 0011 .....(无限循环)

    所以 5.1 = 101.0 0011 0011 0011 0011 0011 0011 0011 0011 ...

    5.1= 1.010 0011 0011 0011 0011 0011 0011 0011 0011 0011... * 2^2

    因为第一位总是为1,如果是0,就移动小数点直到是非0的,所以第一位的1丢弃。
    得到 010 0011 0011 0011 0011 0011 0011 0011 0011....
    取23位 得到 0100 0110 0110 0110 0110 011

    接着看指数部分
    指数是2, 根据规定,指数统一+127再转换为无符号8位2进制数,
    2+127=129 (1000 0001)

    存储的时候指数部分存储在基数之前,这样就有31位了,
    因为5.1是正的,所以符号为是0,存储在指数部分之前

    这样就得到 0100 0000 1010 0011 0011 0011 0011 0011

    我们来看一下机器上是否真的如此

    #include <stdio.h>
    #include <stdlib.h>

    int main(int argc, char *argv[])
    {
        float a=5.1;
        int *i=&a;
        printf("%x", *i);
        system("PAUSE");
        return 0;
    }

    40a33333
    0100 0000 1010 0011 0011 0011 0011 0011

    果真是一样的。

    这个例子就说明了为什么浮点数有时存在这样的问题。
    这个数化为10进制整数的时候,
    由于不可能达到5.1(5.099..)
    所以×100后截取了前面的值 509。 

    32位机器上float 的表示
    对于大小为32-bit的浮点数(32-bit为单精度,64-bit浮点数为双精度,80-bit为扩展精度浮点数),
    1、其第31 bit为符号位,为0则表示正数,反之为复数,其读数值用s表示;
    2、第30~23 bit为幂数,其读数值用e表示;
    3、第22~0 bit共23 bit作为系数,视为二进制纯小数,假定该小数的十进制值为x;

    则按照规定,该浮点数的值用十进制表示为:
    = (-1)^s * (1 + x) * 2^(e - 127)

    对于49E48E68来说,
    1、其第31 bit为0,即s = 0
    2、第30~23 bit依次为100 1001 1,读成十进制就是147,即e = 147。
    3、第22~0 bit依次为110 0100 1000 1110 0110 1000,也就是二进制的纯小数0.110 0100 1000 1110 0110 1000,其十进制形式为0.78559589385986328125,即x = 0.78559589385986328125。

  • 相关阅读:
    Java高级之类结构的认识
    14.8.9 Clustered and Secondary Indexes
    14.8.4 Moving or Copying InnoDB Tables to Another Machine 移动或者拷贝 InnoDB 表到另外机器
    14.8.3 Physical Row Structure of InnoDB Tables InnoDB 表的物理行结构
    14.8.2 Role of the .frm File for InnoDB Tables InnoDB 表得到 .frm文件的作用
    14.8.1 Creating InnoDB Tables 创建InnoDB 表
    14.7.4 InnoDB File-Per-Table Tablespaces
    14.7.2 Changing the Number or Size of InnoDB Redo Log Files 改变InnoDB Redo Log Files的数量和大小
    14.7.1 Resizing the InnoDB System Tablespace InnoDB 系统表空间大小
    14.6.11 Configuring Optimizer Statistics for InnoDB 配置优化统计信息用于InnoDB
  • 原文地址:https://www.cnblogs.com/sunkang/p/2038838.html
Copyright © 2011-2022 走看看