【问题标题】:Looping over a range of floats in C在C中循环一系列浮点数
【发布时间】:2016-10-19 14:56:36
【问题描述】:

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

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

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

这是一个简单的程序(文件名: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$ 

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

如何确保范围始终包含 floor((high - low)/step) + 1 个数字?

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

【问题讨论】:

标签: c for-loop floating-point


【解决方案1】:

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

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

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

在您的情况下,从 0.9 重复减去此值最终会导致第一个有效数字为 a 的数字变为第一个有效数字为 a - 3 的数字:然后您的错误就会显现出来。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多