3

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?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    First, does the same input always produce the same output? Second, try printing the value of `f` in each iteration, I suspect you have floating point rounding errors. Maybe using integers to represent whole cents would make the math easier. – Drew Reese Nov 17 '18 at 01:01
  • it is a poor programming practice to use non-standard C header files, that are not portable. If your in a class, then that is acceptable, just remember that the header file: `cs50.h is not portable. – user3629249 Nov 17 '18 at 02:11
  • in general, using `float` for monetary values is very risky as `float` does not always result in 100 percent correct values. – user3629249 Nov 17 '18 at 02:15
  • OR: For ease of readability and understanding: 1) Please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces. 2) separate code blocks: `for` `if` `else` `while` `do...while` `switch` `case` `default` via a single blank line – user3629249 Nov 17 '18 at 02:19

2 Answers2

3

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.

1

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) {
...
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181