C语言float类型的浮点存储方法

#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。

无奈吧,这个时候想要精确的浮点数的话,
只有自己写高精度算法了。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值