建议3-6:尽量将浮点运算中的整数转换为浮点数

在讨论这个话题之前,我们先看一个示例程序,如代码清单1-22所示。

代码清单1-22 浮点数运算示例


#include <stdio.h>
int main(void)
{
    int i1=321;
    float f1=(float)(i1/9);
    float f2=i1/9.0f;
    float f3=(float)i1/9;
    float f4=(float)i1/9.0f;
    printf("(float)(i1/9)=%f\ni1/9.0f=%f\n(float)i1/9=%f\n
            (float)i1/9.0f=%f\n",f1,f2,f3,f4);
}

在代码清单1-22中,我们定义了一个int类型的变量i1,并将i1除以9的值分别赋给了float类型的变量f1、f2、f3与f4。从表面上来看,最后f1、f2、f3与f4的结果应该完全相同。

但实际情况并非如此,当程序执行语句“float f1=(float)(i1/9)”时,它会先执行表达式“i1/9”,然后将表达式“i1/9”的执行结果35转换成浮点类型再赋给f1,这样就严重地导致数据丢失。执行“float f1=(float)(i1/9)”语句在VC++2010中产生的汇编代码如下所示:


004113A5  mov         eax,dword ptr [i1]
004113A8  cdq
004113A9  mov         ecx,9
004113AE  idiv        eax,ecx
004113B0  mov         dword ptr [ebp-100h],eax
004113B6  fild        dword ptr [ebp-100h]
004113BC  fstp        dword ptr [f1]

但当我们将计算表达中的一个整数转换为浮点类型时,如执行语句“float f2=i1/9.0f”时,它将先执行数据转换操作,即先将变量i1转换为浮点类型,然后再执行除法计算。执行“float f2=i1/9.0f”语句在VC++2010中产生的汇编代码如下所示:


004113BF  fild      dword ptr [i1]
004113C2  fdiv      qword ptr [__real@4022000000000000 (415788h)]
004113C8  fstp      dword ptr [f2]

代码清单1-22的运行结果如图1-36所示。

图1-36 代码清单1-22的运行结果

因此,为了避免出现这种信息丢失的情况,我们在使用整数运算计算一个值并把它赋给浮点变量时,必须将表达式中的一个或全部整数转换为浮点数。