计算机系统:基于x86+Linux平台
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.3.4 C语言中的浮点数类型

C语言中float和double类型分别对应IEEE 754单精度浮点数格式和双精度浮点数格式,相应的十进制有效数字分别为7位和17位左右。

C对于扩展双精度的相应类型是long double,但是long double的长度和格式随编译器和处理器类型的不同而有所不同。例如,Microsoft Visual C++ 6.0版本以下的编译器都不支持该类型,因此,用其编译出来的目标代码中long double和double一样,都是64位双精度;在IA-32上使用gcc编译器时,long double类型数据采用2.3.3节中所述的Intel x87 FPU的80位双精度扩展格式表示;在SPARC和PowerPC处理器上使用GCC编译器时,long double类型数据采用2.3.3节中所述的128位双精度扩展格式表示。

当在int、float和double等类型数据之间进行强制类型转换时,程序将得到以下数值转换结果(假定int为32位)。

• 从int转换为float时,不会发生溢出,但可能有数据被舍入。

• 从int或float转换为double时,因为double的有效位数更多,所以能保留精确值。

• 从double转换为float时,因为float表示范围更小,所以可能发生溢出,此外,由于有效位数变少,因此可能被舍入。

• 从float或double转换为int时,因为int没有小数部分,所以数据可能会向0方向舍入。例如,1.9999被转换为1,-1.9999被转换为-1。此外,因为int的表示范围更小,所以可能发生溢出。将大的浮点数转换为整数可能会导致程序错误,这在历史上曾经有惨痛的教训。

1996年6月4日,Ariane 5火箭初次航行,在发射仅仅37秒钟后就偏离了飞行路线,然后解体爆炸。根据调查发现,原因是控制惯性导航系统的计算机向控制引擎喷嘴的计算机发送了一个无效数据。它没有发送飞行控制信息,而是发送了一个异常诊断位模式数据,表明在将一个64位浮点数转换为16位带符号整数时,产生了溢出异常。溢出的值是火箭的水平速率,这比原来的Ariane 4火箭所能达到的速率高出了5倍。在设计Ariane 4火箭软件时,设计者确认水平速率决不会超出一个16位的整数,但在设计Ariane 5时,他们没有重新检查这部分,而是直接使用了原来的设计。

在不同数据类型之间转换时,往往隐藏着一些不容易被察觉的错误,在航空航天等领域,这种错误有时会带来重大损失,因此,编程时要非常小心。

例2.24 假定变量i、f、d的类型分别是int、float和double,它们可以取除+∞、-∞和NaN以外的任意值。请判断下列每个C语言关系表达式在32位机器上运行时是否永真。

①i==(int)(float)i

②f==(float)(int)f

③i==(int)(double)i

④f==(float)(double)f

⑤d==(float)d

⑥f==-(-f)

⑦(d+f)-d==f

解:①不是,int型有效位数比float型多,i从int型转换为float型时有效位数可能丢失。

②不是,float型有小数部分,f从float型转换为int型时小数部分可能会丢失。

③是,double型比int型有更大的精度和范围,i从int型转换为double型时数值不变。

④是,double型比float型有更大的精度和范围,f从float型转换为double型时数值不变。

⑤不是,double型比float型有更大的精度和范围,d从double型转换为float型时可能丢失有效数字或发生溢出。

⑥是,浮点数取负就是简单地将数符取反。

⑦不是,例如,当d=1.79×10308、f=1.0时,左边为0(因为d+f时f需向d对阶,对阶后f的尾数有效数位被舍去而变为0,故d+f仍然等于d,再减去d后结果为0),而右边为1。