实型变量共分三种:float、double、long double,这三种类型都是以浮点数的方式存储的,遵循IEEE标准。
浮点数的存储方式与编程的关系不大,通常我们编程用到浮点数时只关心变量中存的数值是多少,而不必知道它是怎么存的。这里我们简单介绍float型数据的存储方式以供需要的读者参考,double和long double型的存储与float型类似。
float型的任何数据存储前都要先表示为下面的格式:
(符号)* M*2n
其中:M是一个小数,n是指数。M必须在1.0~2.0之间, 即1.0<=M<2.0,如果不在该范围内,则需调整。
如:30.0,表示为 + 1.875* 24
-0.3925,表示为 -1.57*2-2
然后,计算机用4个字节,分成三部分分别存储符号、指数部分和小数部分。 上面三部分内容所占空间的大小如下表所示:
表7-2 浮点数存储空间的分配
符号位(0或1):占1 位 [第31位]
指数部分(n+127) :占8位 [第30位~第23位]
小数部分 (M-1) :占23位 [第22位~第00位]
细心的读者肯定已经发现了,小数部分存储的是M-1而不是M,指数部分存储的是n+127而不是n,这样设计是有原因的。下面我们分别说明这三部分怎样存储。
(1)符号位:占一位,用0表示正,1表示负。
(2)指数部分:用一个字节存储,本来也有正负的,但是考虑到正负号的处理不方便,所以IEEE标准采用下面的方法:将指数部分加上一个偏移量127后再存储,例如:若实际指数为-2,则存储为125,若实际指数为4,则存储为131,即存储的是“实际指数加上127”。这样规定的目的,是可以不必设指数的符号位。指数位共8位,可表达的范围是0到255 ,而对应的实际指数是-127到+128 。
(3)小数部分:并不是存储浮点数的实际小数。按照规定,实际的小数1 .0<=M<2.0,这样,M的小数点前面将肯定有一个1,因此存储的时候,就可以不存1(将1默认了),而只存小数点后面的纯小数,即M-1。例如1.875,只存0.875
综上所述,对于30.0=+ 1.875* 24: 符号位 : 0 (表示正)
指数部分:10000011 (其值131,表示指数是4)
小数部分: 11100000000000000000000(0.875,表示小数是1.875)
可以用下面的代码验证30.0存储状态:
#include <stdio.h>
int main()
{
union
{
long m;
float x;
}a;
a.x=30;
printf(“%lx\n”,a.m);
return 0;
}
其结果是:41f00000 即二进制的 0100 0001 1111 0000 0000 0000 0000 0000