Issue with while loop executing when it shouldn't (c)

Viewed 78

So as part of a computer science course I've been doing a little bit of C. One of the challenges was to create a program that would tell a hypothetical cashier how many coins they would need in order to give change to a customer. I accomplished this with a set of while loops, the entire program looking like this:

#include <stdio.h>
#include <cs50.h>

int main(void)
{
    float f;
    int i;
    i=0;
do
{
    f = get_float("Input Change: \n");
}
while(f<0);
// This do-while loop uses a get_float operator to get a postive input from the user.
while(f>=0.25)
{
f=f-0.25;
i=i+1;
}
// Each one of these loops represents using one kind of coin. For this one, every time it runs it adds
// one coin to the final tally and removes 25 cents from the change owed.
while(f>=0.10)
{
f=f-0.10;
i=i+1;
}
// Dime loop, subtracts ten from change owed.
while(f>=0.05)
{
f=f-0.0500000;
i=i+1;
}
// Nickel loop, subtracts five from change owed.
while(f>0)
{
f=f-0.01;
i=i+1;
}
// Penny loop, subtracts one from change owed.
printf("You need %i coins.%f\n", i, f);
//This just prints the number of coins needed.
}

The issue is that the last while loop we execute randomly even when there is no reason to do so. For example, $0.42 returns a correct value while $0.15 causes the last while loop to add an extra penny for no reason.

while(f>0)
{
f=f-0.01;
i=i+1;
}

(The problematic while loop in question)

I'm new to programming in general, so this is probably just a problem borne of me doing something stupid, but exactly what I'm doing wrong I do not know. Anyone encountered this before?

2 Answers

It's a precision problem. Equality with floats can be rather problematic. Even though in theory f=0 when you get to the last loop, this fails, and it enters the loop.

A possible workaround is to change it to some number between 0 and 0.01. E.g.

while(f>0.005)

But a better approach would be to use type int to represent money, each unit corresponding to a cent.

With floating point values it gets "weird" comparing them to other floats, like 5, 0.63, and 0.0 because your value may actually be 0.4999999999 or 0.000000000001, which is essentially zero, and in your case fails the condition test and thus adds a final penny when the value then truly goes negative. When comparing floats you must account for this by comparing the difference to some small epsilon value.

float epsilon = 0.0000001;
if ((f - testVal) < epsilon) {
...
}
Related