循环在C中的一系列浮点数

时间:2016-10-19 14:56:36

标签: c for-loop floating-point

我正在尝试用C编写程序来完成以下任务。

  

输入:三个双精度数字a,b和c。

     

输出:从b到a的所有数字,可以通过c的减量达到。

这是一个简单的程序(filename:range.c)。

#include <stdlib.h>
#include <stdio.h>

int main()
{
    double high, low, step, var;
    printf("Enter the <lower limit> <upperlimit> <step>\n>>");
    scanf("%lf %lf %lf", &low, &high, &step);
    printf("Number in the requested range\n");
    for (var = high; var >= low; var -= step)
        printf("%g\n", var);
    return 0;
}

然而,对于某些输入,for循环表现得相当奇怪。例如,以下内容。

10-236-49-81:stackoverflow pavithran$ ./range.o 
Enter the <lower limit> <upperlimit> <step>
>>0.1 0.9 0.2
Number in the requested range
0.9
0.7
0.5
0.3
10-236-49-81:stackoverflow pavithran$ 

我无法弄清楚为什么循环在var = 0.1时退出。而对于另一个输入,它的行为与预期的一样。

10-236-49-81:stackoverflow pavithran$ ./range.o 
Enter the <lower limit> <upperlimit> <step>
>>0.1 0.5 0.1
Number in the requested range
0.5
0.4
0.3
0.2
0.1
10-236-49-81:stackoverflow pavithran$ 

第一种情况下的奇怪行为是否与数字精度有关?

如何确保范围始终包含楼层((高 - 低)/步)+ 1个数字?

我尝试了一种循环遍历浮点数的​​替代方法,其中我将循环变量缩放为整数,并打印循环变量的结果除以使用的缩放。但也许有更好的方式......

1 个答案:

答案 0 :(得分:5)

double循环中使用for作为计数器需要非常仔细地考虑。在许多情况下,最好避免使用。

我相信你知道并非所有十进制精确数字都是精确的二进制浮点数。事实上,对于IEEE754浮点数,只有二元有理数。所以0.5是,但0.4,0.3,0.2和0.1不是。

最接近的IEEE754浮点double到0.2实际上是稍微大一点0.200000000000000011102230246251565404236316680908203125

在你的情况下,从0.9中重复减去这个数字最终导致一个数字,其第一个有效数字是a成为一个数字,其第一个有效数字为a - 3:你的错误就会显现出来。

简单的补救措施是使用整数,每次减去1,并使用step缩放输出。