2

I've seen this particular C program mentioned quite a bit, albeit in some different forms. However I cannot seem to identify the source of my problem, or find another answer that helps. The program compiles and even executes correctly except for a single input: 4.2

The program appears to count the minimum number of coins needed to make the change entered as input, except for 4.2. It outputs 22 instead of 18 as it should (16 quarters, 2 dimes). Any thoughts? I'm auditing an online course, no credit/no academic dishonesty issues.

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

int main(void)
{ 

//quarters, dimes, nickels, and total number of coins. a is float input for exact change.

float a;
int q=0;
int d=0;
int n=0;
int p=0;
int i;

//petitioning input
do
  {
  printf("Hello, how much change do I owe you?\n");
  a = GetFloat();
  }
  while(a<=0);

//converting float a to an integer i
i= a*100;

//four 'while' loops checking quarters nickels dimes pennies and adding to coin count while
while(i>=25)
    {
    i=i-25;
    q++;
    }
while(i>=10 && i<25)
    {
    i=i-10;
    d++;
    }
while(i>=5 && i<10)
    {
    i=i-5;
    n++;
    }

while(i>0 && i<5)
    {
    i= i-1;
    p++;
    }

//printing sum of each coin type 
  {
  printf("%d\n", q+d+n+p);
  }
return 0;    
 }
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Rory
  • 33
  • 1
  • 4
  • 1
    did you check what `a` and the initial `i` contain? – hoijui Jul 29 '15 at 06:58
  • 4
    It's time to learn elementary debugging skills =) Either learn to use a debugger (such as gdb) so you can step through the code and examine data, or simply add `printf` statements at strategic locations to show you important values. I might start by printing out the value of `i` after you first set it. I suspect that your problem is from floating point error. – paddy Jul 29 '15 at 06:58
  • well debugging **a = GetFloat();** is severely needed – SSH Jul 29 '15 at 06:59
  • 5
    Hint: Try printing the value of `i` after `i= a*100;`.... – Sourav Ghosh Jul 29 '15 at 07:02
  • 1
    Shall we close this as a dupe to [Is floating point math broken?](http://stackoverflow.com/q/588004/2173917) All in favor? – Sourav Ghosh Jul 29 '15 at 07:10
  • @SouravGhosh the question is not a duplicate (even though the specifics of floating point representation answer *this* one) – umläute Jul 29 '15 at 07:36
  • @umläute If you have a better dupe, please suggest so. :-) – Sourav Ghosh Jul 29 '15 at 07:38
  • Thank you to all the helpful information, that floating point number issue appears to be the problem!! And thanks Paddy for the printf debugging suggestion. I apologize if this seemed a duplicate to the floating point math question, its hard to know what to search for when you don't know the problem. – Rory Jul 29 '15 at 15:57

3 Answers3

3

You just counterfeited by floating point precision.

You declared

float a;

So, when

a = 4.2; // say

it looks something like

a = 4.19999981

So, i= a*100; is assigned 419 into i instead of 420 (what you are expecting).

Solution You need to convert float a into integer :

(int)(x + 0.5)

So, instead of i= a*100 try

i= a*100 + .5;
mazhar islam
  • 5,561
  • 3
  • 20
  • 41
2

Many numbers cannot be represented correctly in floating point. 4.2 is probably stored as 4.19999999 or something similar.

The conversion from float to integer is not correct and can cause rounding errors:

//converting float a to an integer i
i= a*100; 

In your case, the number 4.2 becomes 419 cents.

Change it to:

//converting float a to an integer i
i= a*100 + 0.5f; 

For further information please read the following article:

What Every Computer Scientist Should Know About Floating-Point Arithmetic, by David Goldberg

Klas Lindbäck
  • 33,105
  • 5
  • 57
  • 82
1

I don't know what is GetFloat() but you have to consider that a float representation of 4.2 will be 4.19999981. You can test it adding printf("a=%.8f", a);

Then when you "convert" float to int the value of i will be 419.

The code that calculates coins is working well, is your input that is not what you think it is.

THIS could help you understand betetr the float to int conversion.

LPs
  • 16,045
  • 8
  • 30
  • 61