分类: C/C++
2013-08-23 10:36:47
这里以C语言的浮点数为例,在IEEE浮点标准下,整数转换为浮点数的过程做一些直观的分析和具体的实现,IEEE浮点数的标准细节详见()。
在C语言中,使用float和double类型数据分别对应单精度和双精度的浮点格式。以float为例,由于float是32位,int在32位机器上也是32位。因此,float必然不能对所有的int进行准确的表示。实际上,在数轴上,浮点数所能表示的数呈非均匀的分布。举例如下图。
. . -3 . . . .-2 . . . -1..........0.........1.. . . . 2 . . . 3. .
图中的点代表float可表示的数,可以看出,在所能表示的数中,接近0的比较密集,远离0的则步长逐渐增大。具体的步长可以根据浮点数标准算出。
以float为例,符号位1位,阶码8位,位数23位。由IEEE浮点的标准可知,非规格化数表示那些非常接近0.0的数。这时候,阶码域全为0.因此,非规格化数的步长为
2-23×2-127 ≈ 1.4×10-45
而非规格化数的范围则约等于 -1.2×10-38 到1.2×10-38 在这个范围内,float能表示的数呈均匀分布。
而int则处在规格化数的范围内。对于规格化数,步长不均匀。步长可表示为
2-23×2E
其中,E的取值范围是-126~+127。显然,随着E增大,步长增大。因此,对于越远离0的区域,步长越大。当E = 30时,步长为128。如下程序是一个验证。
其中,浮点数表示2的30次方,刚阶码值E=30,程序中a数组记录x每次加一的结果,从输出中可以看出,因为步长为128,在0-64次相加中,并没有改变a[i]的值,而在后64次相加中,a[i]则保持为2的30次方+128。
因此,除了不均匀的步长以外,还需要考虑的是舍入的问题。由上面的测试中可知,C语言的舍入方法中,若整数处于步长的前半,则向下舍入,否则向上舍入。而对于刚好处于中间的数,例如上图中a[64],这种与前后的可取的数距离相等,则采用向偶数舍入的原则。即取表示成float形式后,最后一位为偶数(0)的数。
分析到此,开始实现,说白的就是实现一个 float f = float(integer)的功能。函数原型如下:
unsigned float_itof(int i)
把整数i转换为float的表示形式,然后返回对应的4个字节。函数中不能使用float类型及其运算。
代码如下:
对输入i进行 INT_MIN 到 INT_MAX的范围测试,与float(i)的结果逐字节比较。代码正确。