本节书摘来自华章计算机《编写高质量代码:改善c程序代码的125个建议》一书中的第1章,建议3-5,作者:马 伟 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
建议3-5:避免使用浮点数作为循环计数器
由于不同的系统具有不同的浮点数精度限制,为了使代码保持良好的可移植性,我们应该坚决避免使用浮点数来作为循环计数器。
为了让读者更加深刻地了解使用浮点数作为循环计数器会产生的严重后果,接下来看一段示例代码:
float x;
for(x=100000001.0f;x<=100000010.0f;x+=1.0f)
{
printf("%f",x);
}
在上面的代码中,我们使用了一个非常大的浮点数(100000001.0f)来作为循环计数器,并且每循环一次就会使变量x增加1.0f。从表面上来看,上面的代码应该会循环执行10次累加1.0f。
但实际情况并非如此,相对于浮点数(100000001.0f)而言,如果一个浮点循环计数器的增量太小,那么它就无法在它的精度下更改值。因此,在许多编译器中,上面的这段代码将会产生一个无限循环。例如在VC++ 2010中的运行结果如图1-34所示。
https://yqfile.alicdn.com/00f71d12a682248ee5cd4d24aa1875ccaccec7b6.png" >
上面的示例代码演示了以一个大的浮点数(100000001.0f)来作为循环计数器的情况。或许这个时候有人会想,如果换用一个小的浮点数作为循环计数器结果会怎样呢?
带着这个问题,我们继续看下面的示例代码:
float x;
for(x=0.1f;x<=1.0f;x+=0.1f)
{
printf("%f\n",x);
}
很显然,上面的代码使用了一个比较小的浮点数(1.0f)作为循环计数器,并且每循环一次变量x就会增加0.1f。但是在这里问题出现了,十进制的0.1用二进制表示是一个重复的无限循环小数,也就是说无法准确地使用二进制表示,它的精度会受损。如果在VC++ 2010中运行上面这段代码,那么循环只会执行9次,如图1-35所示。
由上面的两个示例代码可以看出,不论是使用大的还是小的浮点数来作为循环计数器,都会导致出乎意料的结果。因此,我们应该避免使用浮点数作为循环计数器。如果必须这么做,我们也应该想办法将其转换成整数的形式进行。如下面的示例代码所示:
float x;
size_t i;
for(i=1;i<=10;i+=1)
{
x=i/10.0f;
printf("%f\n",x);
}