我正在尝试用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个数字?
我尝试了一种循环遍历浮点数的替代方法,其中我将循环变量缩放为整数,并打印循环变量的结果除以使用的缩放。但也许有更好的方式......
答案 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
缩放输出。