首先给出查阅资料的一些链接:
http://www.kuqin.com/language/20100606/85209.html
http://www.cnblogs.com/jillzhang/archive/2007/06/24/793901.html
http://en.wikipedia.org/wiki/IEEE_754-1985
首先来看两个例子:
#include
#include
union stu
{
int i;
char c;
float f;
}a;
int main()
{
FILE *fp;
fp=fopen("a.txt","w");
fprintf(fp,"%d\n",sizeof(char));//1
fprintf(fp,"%d\n",sizeof(short));//2
fprintf(fp,"%d\n",sizeof(int));//4
fprintf(fp,"%d\n",sizeof(long));//4
fprintf(fp,"%d\n",sizeof(float));//4
fprintf(fp,"%d\n",sizeof(double));//8
a.i=97;//int 类型在内存中占4个字节,97的二进制表示为00000000 00000000 00000000 01100001
fprintf(fp,"%d\n",a.i);
fprintf(fp,"%c\n",a.c);
fprintf(fp,"%.100f\n",a.f);//找到某一float类型数在内存中的存储为00000000 00000000 00000000 01100001
fprintf(fp,"%.100f\n",pow(2,-126)*(pow(2,-17)+pow(2,-18)+pow(2,-23)));
fclose(fp);
return 0;
}
运行结果:a.txt中内容为
1
2
4
4
4
8
97
a
0.0000000000000000000000000000000000000000001359259510395072600000000000000000000000000000000000000000
0.0000000000000000000000000000000000000000001359259510395072600000000000000000000000000000000000000000
#include
#include
union stu
{
int i;
char c;
float f;
}a;
int main()
{
FILE *fp;
fp=fopen("a.txt","w");
fprintf(fp,"%d\n",sizeof(char));//1
fprintf(fp,"%d\n",sizeof(short));//2
fprintf(fp,"%d\n",sizeof(int));//4
fprintf(fp,"%d\n",sizeof(long));//4
fprintf(fp,"%d\n",sizeof(float));//4
fprintf(fp,"%d\n",sizeof(double));//8
a.f=97;//float 类型在内存中占4个字节,浮点数97在内存中的二进制表示为0 10000101 1000010 00000000 00000000
fprintf(fp,"%d\n",a.i);//0 10000101 1000010 00000000 00000000=1120010240
fprintf(fp,"%c\n",a.c);//00000000=null
fprintf(fp,"%.100f\n",a.f);
fprintf(fp,"%.100f\n",pow(2,-126)*(pow(2,-17)+pow(2,-18)+pow(2,-23)));
fclose(fp);
return 0;
}
运行结果:a.txt中内容为
1
2
4
4
4
8
1120010240
97.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0.0000000000000000000000000000000000000000001359259510395072600000000000000000000000000000000000000000
第一个程序的a.f为什么为0.0000000000000000000000000000000000000000001359259510395072600000000000000000000000000000000000000000?
第二个程序的a.c=空?,a.i=1120010240?
这里就涉及到float类型的数在内存中的存储格式问题。
无论是单精度还是双精度在存储中都分为三个部分:
其中单精度float的存储方式:
而双精度double的存储方式为:
R32.24和R64.53的存储方式都是用科学计数法来存储数据的,比如8.25用十进制的科学计数法表示就为:8.25*,而120.5可以表示为:1.205*
。而我们傻蛋计算机根本不认识十进制的数据,他只认识0,1,所以在计算机存储中,首先要将上面的数更改为二进制的科学计数法表示,8.5用二进制表示可表示为1000.1。118.5用二进制表示为:1110110.1,用二进制的科学计数法表示1000.1可以表示为1.0001*
,1110110.1可以表示为1.1101101*
,任何一个数都的科学计数法表示都为1.xxx*
,尾数部分就可以表示为xxxx,第一位都是1,可以将小数点前面的1省略,所以23bit的尾数部分,可以表示的精度却变成了24bit,道理就是在这里,那24bit能精确到小数点后几位呢,我们知道9的二进制表示为1001,所以4bit能精确十进制中的1位小数点,24bit就能使float能精确到小数点后6位,而对于指数部分,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127~128了,所以指数部分的存储采用移位存储,存储的数据为元数据+127。
首先看下8.5,用二进制的科学计数法表示为:1.0001*
按照上面的存储方式,符号位为:0,表示为正,指数位为:3+127=130 ,尾数部分为0001,故8.5的存储方式如下图所示:
而单精度浮点数118.5的存储方式如下图所示:
那么如果给出内存中一段数据,并且告诉你是单精度存储的话,你如何知道该数据的十进制数值呢?其实就是对上面的反推过程,比如给出如下内存数据:0100001011101101000000000000,首先我们现将该数据分段,0 1000 0101 110 1101 0000 0000 0000 0000,在内存中的存储就为下图所示:
根据我们的计算方式,可以计算出,这样一组数据表示为:1.1101101*=118.5