当前位置:文档之家› C语言float类型浮点数的存储方法

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

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,可是机器居然输出509。

我试着把5.1改成5.5,一切正常。

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"); /* 将PAUSE送到system command line去执行 */
return 0;
}
40a33333
0100 0000 1010 0011 0011 0011 0011 0011
果真是一样的。

这个例子就说明了为什么浮点数有时存在这样的问题。

这个数化为10进制整数的时候,
由于不可能达到5.1(5.099..)
所以×100后截取了前面的值 509。

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

-----------------------------------------------------------------------------------
乘数、被乘数都要先转化为二进制,二进制的乘法远比十进制简单,比如乘数是1011,只需将将被乘数分别左移3位、1位,移动后补入0,并将这三个数(被乘数左移3位的、被乘数左移1位的及未移位的被乘数)在累加器中相加,所得总和就是积,根据需要积可再转化为十进制。

除法与乘法类似,只不过将左移改为右移,加改成减。

实际上减也是通过取补码后再加,因此计算机芯片上的累加器是最繁忙的部分
------------------------------------------------------------------------------------- IEEE 754 用科学记数法以底数为 2 的小数来表示浮点数。

IEEE 浮点数用 1 位表示数字的符号,用 8 位来表示指数,用 23 位来表示尾数,即小数部分。

作为有符号整数的指数可以有正负之分。

小数部分用二进制(底数 2)小数来表示,这意味着最高位对应着值 ?(2 -1),第二位对应着 ?(2 -2),依此类推。

对于双精度浮点数,用 11 位表示指数,52 位表示尾数。

相关主题