Pavithran Iyer - 1 year ago 60
C Question

# Looping over a range of floats in C

I am trying to write a program in C to accomplish the following task.

Input: Three double-precision numbers, a, b, and c.

Output: All the numbers from b to a, that can be reached by decrements of c.

Here is a simple program (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;
}
``````

However, the for loop behaves rather bizarrely for some inputs. For instance, the following.

``````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\$
``````

I cannot figure out why the loop quits at var = 0.1. While for another input, it behaves as expected.

``````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\$
``````

Had the weird behaviour in the first situation got something to do with numeric precision?

How can I ensure that the range will always contain floor((high - low)/step) + 1 numbers?

I have tried an alternate method of looping over floats, where I scale the loop variables to integers, and print the result of the loop variable divided by the scaling used. But there's perhaps a better way...

Using a `double` as a counter in a `for` loop requires very careful consideration. In many instances it's best avoided.
The closest IEEE754 floating point `double` to 0.2 is actually the slightly larger `0.200000000000000011102230246251565404236316680908203125`.
In your case a repeated subtraction of this from 0.9 eventually causes a number whose first significant figure is `a` to become a number whose first significant figure is `a - 3`: your bug then manifests itself.
The simple remedy is to work in integers, decement by 1 each time, and scale your output using `step`.