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。

  • 相关阅读:
    Minimum Depth of Binary Tree leetcode java
    Maximum Depth of Binary Tree leetcode java
    Symmetric Tree leetcode java
    Same Tree leetcode java
    Binary Tree Postorder Traversal leetcode java
    Binary Tree Preorder Traversal leetcode java
    Binary Tree Inorder Traversal leetcode java
    Combinations leetcode java
    一键清除Centos iptables 防火墙所有规则
    阿里云centos7.7x64安装open,并配置ip转发和nat伪装
  • 原文地址:https://www.cnblogs.com/sunkang/p/2038838.html
Copyright © 2011-2022 走看看