浮点数操作实验
实验目的
深入理解浮点数的二进制表示及操作
实验内容
本实验由一组浮点程序的实现问题构成
规则参见bits.c中的“FLOATING POINT CODING RULES”
允许的规则:
使用条件语句和循环语句
使用int和unsigned类型的变量和常量
使用任意的算术、逻辑或是比较操作
禁止的规则:
定义或使用任意的宏
定义额外的函数
函数调用、类型转换
使用除int和unsigned之外的数据类型,包括数列、结构体和联合体等
使用浮点数相关的类型、操作或是常量
实验步骤
floatScale2
- 阶码的编码为e,尾数的小数部分为f,符号为s;
- 浮点数分三种情况:
- 规格化的:如果是
e==254
,返回正负无穷,否则返回x的阶码加1的值即可。 - 非规格化的:如为0,返回0。否则返回x的尾数乘以2的值。
- 无穷大和NaN:返回x的值。
- 规格化的:如果是
uint32_t floatScale2(uint32_t x)
{
uint32_t e = (x<<1)>>24;
uint32_t f = (x<<9)>>9;
uint32_t s = (x>>31)<<31;
if(e!=0 && e!=255)
{
if(e==254)return s+((e+1)<<23);
return s+((e+1)<<23)+f;
}
else if(e == 0)
{
if(f==0)return x;
return s+(e<<23)+f*2;
}
else
return x;
}
floatFloat2Int
- 阶码的编码为e,尾数为f,符号为s;
- 浮点数分三种情况:
- 规格化的:阶码的值E为e-127,分两种情况:
- E>=0:转换为整数大于1,分两种情况:
- 正数:分三种情况:
- E<23:根据阶码扩大尾数不足23位,有
23-E
位舍去,将尾数左移(23-E)
位,加上符号位返回。 - 23<=E<31:根据阶码能完全扩大尾数,且不会溢出,将尾数右移
(E-23)
位,加上符号位返回。 - E>=31:根据阶码扩大尾数发生溢出,返回
0x80000000u
。
- E<23:根据阶码扩大尾数不足23位,有
- 负数:和正数一样分为三种情况
E<31,23<=E<31,E>31
,不同的是符号s仅在最高位为1,有问题。根据f的位数为24-(23-E)=E+1
或者(E-23)+24=E+1
得到符号位应该是(0xffffffff<<(1+E))
- 正数:分三种情况:
- E<0:转换为整数小于1,返回0;
- E>=0:转换为整数大于1,分两种情况:
- 无穷大或NaN:返回
0x80000000
。 - 非规格化的:远小于1,返回0。
- 规格化的:阶码的值E为e-127,分两种情况:
uint32_t floatFloat2Int(uint32_t x)
{
uint32_t e = (x<<1)>>24;
uint32_t f = ((x<<9)>>9)+0x00800000;
uint32_t s = (x>>31)<<31;
if(e!=0 && e!=255)
{
int32_t E =e-127;
uint32_t F1=(f>>(23-E));
uint32_t F2=(f<<(E-23));
if(E>=0)
{
if(s==0)
{
if(E<23)
return s+F1;
else if(E<31)
return s+F2;
return 0x80000000u;
}
else
{
uint32_t t = (0xffffffff<<(1+E));
if(E<23)
return t+F1;
else if(E<31)
return t+F2;
return 0x80000000u;
}
}
return 0;
}
if(e==255)
return 0x80000000u;
return 0;
}
floatPower2
- 单精度浮点数的规格化数精度为**-126~127**
- x<=-127,非规格化数,返回0。
- x>127,无穷大或NaN,返回
0x7f800000
。 - -126<=x<=127,
(x+127)
为阶码E的对应编码,返回(x+127)<<23
。
uint32_t floatPower2(int32_t x)
{
if(x<=-127)return 0;
else if(x>127)return 0x7f800000;
return (x+127)<<23;
}
实验结果和探索
运行结果截图
探索题目
上述题目如果限制为双精度浮点数,有何差别
答:在三个函数中,移位均不同。在floatScale2()
中对E的情况判断的值为0和
2
11
2^{11}
211。在floatFloat2Int()
函数中E在正数或者负数中判断情况为52位和63位。在floatPower2()
中精度为
−
2
10
+
1
-2^{10}+1\quad
−210+1 ~
2
10
\quad 2^{10}
210。
异常情况
-
1/3的浮点数表示和误差分析:浮点表示为 1.01010101010101010101010 × 2 − 2 1.01010101010101010101010\times2^{-2} 1.01010101010101010101010×2−2,即
00111110101010101010101010101010b
,误差为 0.1010.... × 2 − 25 0.1010....\times2^{-25} 0.1010....×2−25。 -
无效情况。
-
除以0:正或负 ∞ \infty ∞(如果分子非零),或者NAN(如果分子为零)。
-
阶码下溢:阶码下溢到无法用非规格化数表示,则结果为0。
-
阶码上溢:阶码上溢,则结果溢出。