0

I have this function:

int change(float c)
{
    float coins[] = {0.25, 0.10, 0.05, 0.01};
    int count[] = {0, 0, 0, 0};

    while(c > (0.00))
    {
        printf("I entered here\n");
        if((c-coins[0]) >= (0.00))
        {
            c -= coins[0];
            count[0]++;
            printf("-0.25, c = %.2f\n", c);
        }
        else if((c-coins[1]) >= (0.00))
        {
            c -= coins[1];
            count[1]++;
            printf("-0.10, c = %.2f\n", c);
        }
        else if((c-coins[2]) >= (0.00))
        {
            c -= coins[2];
            count[2]++;
            printf("-0.05, c = %.2f\n", c);
        }
        else if((c-coins[3]) >= (0.00))
        {
            c -= coins[3];
            count[3]++;
            printf("-0.01, c = %.2f\n", c);
        }
    }
    printf("(%d) 25 cents, (%d) 10 cents, (%d) 5 cents, (%d) 1 cents\n",
           count[0], count[1], count[2], count[3]);
    int total = count[0] + count[1] + count[2] + count[3];

    return total;
}

And whenever I try to enter 0.06 or 0.07, or any float number that will cause it to reach the last else if clause (the else if((c-coins[3]) >= (0.00))) it will cause an infinite loop.

Whereas if I enter 0.25, 0.10, 0.05 and their respective perfect multiples, the function goes smoothly. (Because maybe it wont reach the last else if clause).

And so when I debugged (using simple printf techniques), I found out that the variable c still enters the while loop even though it has reached 0.00. On some occasions, it would even reach -0.00 or -0.01 (and this only works if I changed the else if((c-coins[3]) >= (0.00)) to else only).

Example (assuming the else if in the code is already else only):
Input: 0.06

c-0.05, c = 0.01
c-0.01, c = -0.00 **<- WTF** 
(0) 25 cents, (0) 10 cents, (1) 5 cents, (1) 1 cents
Total Coins: 2

Someone explain this to me? Am I missing out some rules regarding float numbers here? Or some errors are caused by that last else if clause of mine?

Note: Changing the last else if to else may work but can affect the final answer. Also, changing the while condition to -0.00 or 0.001 doesn't work.

mafso
  • 5,264
  • 2
  • 16
  • 39
anobilisgorse
  • 856
  • 9
  • 23

1 Answers1

6

Floating point values (typically) use a binary representation. The only fraction in your coins array that can be represented exactly is 0.25. All the other values will be slightly smaller or larger than the correct value. This means that every arithmetic operation on these values, even simple substraction, will introduce small computation errors that will cause your comparisons and output to be faulty.

The best solution, in my opinion, is to use only integer types and perform all your calculations in cents (hundreds). You can print out the amounts using division and modulo.

int change(int cents)
{
   int coins[] = {25, 10, 5, 1};
   int count[] = {0, 0, 0, 0};

   while(cents > 0)
   {
     if((c-coins[0]) >= 0)
     {
        c -= coins[0];
        count[0]++;
        printf("-0.25, c = %d.%02d\n", c/100, c%100);
     }
     /* and so on */

You may want to use unsigned or long or both depending on your needs.

Nisse Engström
  • 4,636
  • 22
  • 26
  • 40