IEEE754 国际标准浮点数存储格式实验
测试报告
学号:
姓名:
E10914089
郜伟
班级:09 级计算机科学与技术一班
目录
一、IEEE754 国际标准简介....................................................... 3
二、浮点数分类.........................................................................4
1. 规格化..............................................................................4
2. 非规格化..........................................................................4
3. 特殊数值..........................................................................4
三、浮点数存储格式................................................................. 4
1.存储格式介绍.................................................................... 4
2.存储格式验证.................................................................... 5
3.浮点数的溢出.................................................................... 9
四、小结...................................................................................11
IEEE754 国际标准浮点数存储格式实验
测试报告
【摘要】浮点数的表示形式在不同的算法下千变万化,为了方便算法
软件、数据等之间的移植和交流,1985 年 IEEE 协会制定了 IEEE754
标准。本文在查阅和分析大量有关 IEEE754 国际标准的资料基础上,
利用 C 语言编程规范,以实验的形式将浮点型储存格式在 win7 系统
上显示出来,加深了对 IEEE754 标准的理解。
【关键词】IEEE ;EEE754;浮点数;浮点数存储格式;规格化;C
语言测试
一、IEEE754 国际标准简介
在 IEEE754 标准之前,世界上没有浮点数统一的表示形式。这样就导致了
许许多多的浮点数表示格式出现。随着互联网的普及和技术间交流,这种
没有统一标准的浮点数表示方法逐渐成为学术交流中得障碍。
为 便 于 软 件 的 移 植 , 浮 点 数 的 表 示 格 式 应 该 有 统 一 标 准 。 1985 年 IEEE
(Institute of Electrical and Electronics Engineers)提出了 IEEE754
标准。
该标准规定基于基数为 2 的浮点数数 N,从逻辑上用三元组{S,M,E}表示,
储存格式如表 1 所示:
表 1
高位---------------------------------------------------低位
S
E
M
S 表示 N 的符号位。当 N>0 时,S=0;当 N<0 时,S=1。
E 表示 N 的指数位,位于 S 和 M 之间。位数不一定,由表示的浮点数的
精度型确定。
M 在存储格式的末尾,故称为 N 的尾数位。M 也称有效数字位、系数位,
有时也被称为小数。
根据 IEEE754 标准,三元组{S,E,M}与 N 的映射关系如下:
N=(-1)S×m×2e
此时需要增设两个变量 m 和 e。此处的 m 与 M,e 与 E 具有一定的关系,将
在下文具体阐述。
二、浮点数分类
根据存储格式中的指数 E 的值,将浮点数分成三种类型:规格化、非规格化、特
殊数值。
1. 规格化
当 E 的二进制位既不全为 0 也不全为 1 时,则 N 为规格化形式。此时 e 被称为
偏置(biased)形式的整数,此时增设偏置量 bias,则此时 e 与 E,m 与 M 的映
射关系为:
e=|E|-bias , bias=2k-1-1
k 为 E 的位数,单精度时 k=8,bias=127;双精度时 k=11,bias=1023
m=|1.M|
如:E 为 10000100,M 为 101 时,|E|=132,e=132-127=5,m=|1.M|=|1.101|=1.625。
2. 非规格化
当 E 的二进制位全为 0 时,N 则为非规格化形式。此时 e 与 E,m 与 M 的映射关
系为:
E=1-bias
M=|0.M|
非规格化数可以方便地表示 0 或者非常接近 0 的浮点数。如将 S=1,其他置 0,
则得出-0.0;同理,可得到+0.0。其他小数接近 0,并且均匀接近 0 时,称为“逐
渐下溢”属性。
3. 特殊数值
当 E 的的二进制位全为 1 时,则 N 为特殊数值。若 M 得二进制位全为 0,则 N
表示无穷大,若 S 为 1 则为负无穷大,若 S 为 0 则为正无穷大;若 M 的二进制
位不全为 0(至少一位不为 0),表示 NaN(Not a Number),表示 N 不是一个合法
实数或无穷或者为未初始化。
实数 的 IEEE754 标准的浮点数格式为:具体有三种形式: IEEE754 三种浮
点数的格式参数
三、浮点数存储格式
1.存储格式介绍
根据 C 语言的格式,浮点型有三种类型存在,即为 float、double、long double
三种类型,此三种类型的内存大小以及在储存时的格式为表 2 所示:
类型
表 2
存储位数
偏移值 bias
数符(s) 阶码(E) 尾数(M) 总位数
十六进制 十进制
单精度(Float)
双精度(Double)
1 位
1 位
8 位
23 位
32 位
0x7FH
+127
11 位
52 位
64 位
0x3FFH
+1023
增长型(long double) 1 位
15 位
64 位
80 位
0x3FFFH
+16383
第三种类型很少使用,故本文将不讨论其在内存中的存储格式。只讨论单
精度和双精度的储存方式。
2.存储格式验证
下文所写的程序都在 WIN7 旗舰系统中 Visual C++6.0 上运行成功。利用 C
库中的 库的 itoa(int i,string s,2);函数可将整型的 i 转化
称二进制存放在字符串 s 中。通过将 s 字符串显示出来就可直观地看到浮点
型数在内存中存在格式情况。
2.1 单精度内存存储格式
2.1.1 测试代码与解释
# include
# include
void main(){
float a;//浮点数 a
unsigned int *p=(unsigned int *)&a;
//将浮点数转化为无符号型的整数便于读取二进制数
char s[32];
int i=0;
printf("Please input a float:");
scanf("%f",&a);
printf("\n 浮点数为:%f\n",a);
printf("内存中数为:%x\n",*p);//内存中存储方式
if
(*p==0){
for(;i<32;i++) s[i]='0';//若为 0 时全部赋值为 0
}
else{
if((*p)<0x80000000){s[0]='0';i=1;printf("0x8");}
//二进制转换时首位为第一个 1 之前的 0 无法存储到
if((*p)<0x40000000){s[0]='0';s[1]='0';i=2;printf("0x4");}
itoa(*p,s+i,2);//转化为二进制数
}
printf("二进制数是:\n",s);
for(int n=0;n<64;n++) printf("-");//画边框
printf("\n");
for(i=0;i<32;i++){
if(i==1||i==9) printf("
printf("%c",s[i]);
");//将 S,E,M 三个部分区分开来
}
printf("\n");
for(int nn=0;nn<64;nn++) printf("-");
printf("\n");
}
2.1.2 实例介绍
①取浮点数为-0.5,根据上文中得规格化分析可得一下推导:
-0.5(10 进制)=-0.1(2 进制)=-1.0×2-1(2 进制,-1 是指数),这里
s=1,M 为全 0,E-127=-1,E=126(10 进制)=01111110(2 进制),则存储
形式为:1 01111110 000000000000000000000000=BF000000(16 进制)。
运行程序结果如图 1 左所示
图 1
若为 1.625,则可根据规格化可知此时 M 为 0.625=101,e=0,
E=e+bias=0+127=01111111。即如上右图所示。
②+0 和-0 在内存中存在状态如图 2 所示:
图 2
③内存中全为 1 时的存储情况:将上文中得代码改为如下:
void main(){
unsigned int b=0xffffffff;//将内存中的数全部赋值为 1
float *c=(float *)&b, a=*c;
unsigned int *p=(unsigned int *)&a;
char s[32];
int i=0;
printf("浮点数为:%f\n",a);
printf("内存中数为:%x\n",*p);//内存中存储方式
if
for(;i<32;i++) s[i]='0';//若为 0 时全部赋值为 0
}
(*p==0){
else{
if((*p)<0x80000000){s[0]='0';i=1;printf("0x8");}
//二进制转换时首位为第一个 1 之前的 0 无法存储到
if((*p)<0x40000000){s[0]='0';s[1]='0';i=2;printf("0x4");}
itoa(*p,s+i,2);//转化为二进制数
}
printf("二进制数是:\n",s);
for(int n=0;n<64;n++) printf("-");
printf("\n");
for(i=0;i<32;i++){
if(i==1||i==9) printf("
printf("%c",s[i]);
}
");
printf("\n");
for(int nn=0;nn<64;nn++) printf("-");
printf("\n");
}
此为特殊数值,运行程序显示为图 3 左图:
图 3
若改动程序 b=0x7f800000;此时显示结果如图 3 右图所示。
注释:对于阶码 E 的存储形式因为是 127 的偏移,所以在计算其移码时与人
们熟悉的 128 偏移不一样,正数的值比用 128 偏移求得的少 1,负数的值多
1,为避免计算错误,方便理解,常将 E 当成二进制真值进行存储。
2.2 双精度内存格式
双精度 double 型和单精度 float 型主要的区别就是所占内存不同,一个是 8 字节,
一个是 4 字节。只需要通过修改程序中的显示次数即可,代码如下(头文件略):
void zhuanhuan(unsigned int &pi){//打印二进制格式函数
char tem[32];
unsigned int *p=π
printf("内存中数为:%x%x\n",*p,*(p-1));
int i=0,flag=2;
printf("\n");
for(;i<2;i++){
if
(*(p-i)==0){
for(int ii=0;ii<32;ii++) {
if(flag&&(ii==1||ii==12)) {printf("
");flag--;}
printf("0");//若为 0 时全部赋值为 0
}
continue;
}
else{
int mm=0;
{tem[0]='0';mm=1;printf("0x8\n");}
//二进制转换时首位为第一个 1 之前的 0 无法存储到
if((*(p-i))<0x40000000)
{tem[0]='0';tem[1]='0';mm=2;printf("0x4\n");}
itoa(*(p-i),tem+mm,2);//转化为二进制数
for(int ii=0;ii<32;ii++)
if((*(p-i))<0x80000000)
if((ii==1||ii==12)&&flag!=0)
{printf("
printf("%c",tem[ii]);}
{
");flag--;}
}
}
return ;
}
void main(){//主函数
double a;
unsigned int *p=(unsigned int *)&a;
int i=0;
printf("请输入一个浮点数(双精度):");
scanf("%lf",&a);
printf("浮点数为:%lf\n",a);
printf("内存中数为:%x%x\n",*(p+1),*p);//内存中存储方式
printf("二进制数是:\n");
for(int n=0;n<64;n++) printf("-");
printf("\n");
zhuanhuan(*(p+1));
printf("\n");
for(int nn=0;nn<64;nn++) printf("-");
printf("\n");
}
将单精度中测试的六个数据在双精度的程序运行后的结果如图 4、5、6、7、8、
9 所示。
图 4
图 5