Ben
Ben

Reputation: 3

Printf Problem with While Loop

I'm creating a temperature converter in C. Basically, you input a minimum and maximum value in degrees Celsius, along with a step, and it displays that information in a list, along with the Fahrenheit equivalent. On some occasions, I have noticed the last Fahrenheit entry not being displayed when it should. For example, when you input a lower limit of 10, a higher limit of 30, and a step of 4, it cuts off the last Fahrenheit temperature. I know it's something to do with the last while loop, but I just can't figure it out.

#include <stdio.h>

int main (int argc, const char * argv[]) {
double l, h, s;
double lf, hf, sf;
/* Number rows in tables */
int num1, num2;
num1 = 1;
num2 = 1;

/* Lower limit input */
printf("Please give a lower limit: ");
scanf("%4lf", &l);
while (l < 0) {
        printf("Lower limit must be greater than 0: ");
        scanf("%4lf", &l);
}

/* Stores value for Fahrenheit conversion */
lf = l;

/* Higher limit input */
printf("Please give a higher limit: ");
scanf("%4lf", &h);
while (h <= l) {
        printf("Higher limit must be greater than lower limit: ");
        scanf("%4lf", &h);
}

while (h >= 50000) {
        printf("Higher limit must be less than 50000: ");
        scanf("%4lf", &h);
}

hf = h;

/* Step input */
printf("Please input step: ");
scanf("%4lf", &s);
while (s <= 0) {
        printf("Step must be greater than 0: ");
        scanf("%4lf", &s);
}

while (s >= h - l) {
        printf("Step must be less than the difference in temperatures: ");
        scanf("%4lf", &s);
}

sf = s;

/* Celsius table */
printf("\nCelsius\n-------\n");
while (l <= h) {
    printf("%i. %4lf\n", num1, l);
    num1++;
    l = l + s;
}

/* Fahrenheit table */
printf("\nFahrenheit\n----------\n");
/* Converts Celsius to Fahrenheit */
lf = (lf * 1.8) + 32;
hf = (hf * 1.8) + 32;
sf = sf * 1.8;
printf("Lower input: %4lf\n", lf);
printf("Higher input: %4lf\n", hf);
printf("Step: %4lf\n----------\n", sf);
/* This while loop sometimes cuts off the last entry */
while (lf <= hf) {
    printf("%i. %4lf\n", num2, lf);
    num2++;
    lf = lf + sf;
}

return 0;

}

Upvotes: 0

Views: 1001

Answers (4)

Andreas Brinck
Andreas Brinck

Reputation: 52519

The problem is with comparing the doubles, you might get into a situation where something like 10 + 1.8 evaluates to 11.800000001 and thus missing the end value.

The solution to your problem would be to first calculate the number of steps:

int steps = (h - l) / s + 1; //Might want to apply rounding

And then use a for/while loop over the integer variable instead:

for (int i = 0; i < steps; ++i) {
    double t = l + (h - l) * i / (steps - 1);
}

for (int i = 0; i < steps; ++i) {
    double tf = lf + (hf - lf) * i / (steps - 1);
}

Upvotes: 3

Alok Save
Alok Save

Reputation: 206546

while (lf <= hf) 

You are comparing Double values, You will face problems of Precison & Rounding Errors, Most likely that causes the last iteration to not execute at all.

This answer of mine, should be a good read.

Upvotes: 2

TheIronKnuckle
TheIronKnuckle

Reputation: 7294

Directly after your last while loop, add the following code (and don't forget to #include assert.h):

printf("lf = %f, hf = %f\n", lf, hf);
assert(lf == hf);

you should get this output:

Celsius
-------
1. 10.000000
2. 14.000000
3. 18.000000
4. 22.000000
5. 26.000000
6. 30.000000

Fahrenheit
----------
Lower input: 50.000000
Higher input: 86.000000
Step: 7.200000
----------
1. 50.000000
2. 57.200000
3. 64.400000
4. 71.600000
5. 78.800000
lf = 86.000000, hf = 86.000000
Assertion failed: lf == hf, file randomdudescode.c, line 77

Which is incredibly confusing, because obviously lf == hf. This illustrates one of the quirks of C and floating point tomfoolery in general. You have to deal with rounding errors and imprecision.

Upvotes: 0

Sleeperson
Sleeperson

Reputation: 612

Choose a precision and compare it with the difference between hf and lf(abs value). Also keep in mind with a random fixed step you will not always reach the top value of the interval. it might work if step divides h-l but it won't work otherwise.

Upvotes: 0

Related Questions