-1

I have written the following code to determine how to pay out change:

#include<stdio.h>

#define twentyDollar 2000
#define tenDollar 1000
#define fiveDollar 500
#define oneDollar 100
#define quarters 25
#define dimes 10
#define nickels 5
#define pennies 1

int round(double change)
{
    return (int)(change + 0.5);

}

void main(void) {

int change, temp;
double cost, paid;


int numberOfTwentyDollar = 0;
int numberOfTenDollar = 0;
int numberOfFiveDollar = 0;
int numberOfOneDollar = 0;
int numberOfQuarters = 0;
int numberOfDimes = 0;
int numberOfNickels = 0;
int numberOfPennies = 0;

printf("Enter cost ($): ");
scanf("%lf", &cost);

printf("Enter amount tendered ($): ");
scanf("%lf", &paid);

change = round((paid - cost) * 100.0);

temp = change;

while (temp > 0) {
if (temp > twentyDollar)
{
    numberOfTwentyDollar = temp / twentyDollar;
    temp = temp % twentyDollar;
}

else if(temp > tenDollar)
{
    numberOfTenDollar = temp / tenDollar;
    temp = temp % tenDollar;
}

else if(temp > fiveDollar)
{
    numberOfFiveDollar = temp / fiveDollar;
    temp = temp % fiveDollar;
}

else if (temp > oneDollar)
{
    numberOfOneDollar = temp / oneDollar;
    temp = temp % oneDollar;
}

else if(temp > quarters)
{
    numberOfQuarters = temp / quarters;
    temp = temp % quarters;
}

else if(temp > dimes)
{
    numberOfDimes = temp / dimes;
    temp = temp % dimes;
}

else if(temp > nickels)
{
    numberOfNickels = temp / nickels;
    temp = temp % nickels;
}

else if(temp > pennies)
{
    numberOfPennies = temp / pennies;
    temp = temp % pennies;
}

}

printf("Change is $%.2d\n", change);

printf("$20 bills: %d\n", numberOfTwentyDollar);
printf("$10 bills: %d\n", numberOfTenDollar);
printf("$5 bills: %d\n", numberOfFiveDollar);
printf("$1 bills: %d\n", numberOfOneDollar);
printf("quarters: %d\n", numberOfQuarters);
printf("dimes: %d\n", numberOfDimes);
printf("nickels: %d\n", numberOfNickels);
printf("pennies: %d\n", numberOfPennies);
}

When I input my sample values of cost ($23.18) and amount tendered ($100.00) the output is all correct, however the "change" displayed is $7682 when it is suppose to be $76.82. Any pointers on what I am doing wrong? Thank you!

MatthewS
  • 455
  • 2
  • 7
  • 22
  • You multiple change by 100 at `change = round((paid - cost) * 100.0);`. If you don't undo that later, it'll be 100 too much. – matsjoyce Sep 27 '14 at 19:26
  • 3
    You're using `change` (and then `temp`) in order to denote the number of cents, **not the number of dollars**!!! BTW, this question makes one very doubtful with regards to the statement "I have written the following code". Personally, I find it hard to believe that you've written it yourself and ended up asking this question (no offense please). – barak manos Sep 27 '14 at 19:31
  • Sometimes people make stupid mistakes or get stumped in places where they shouldn't. – MatthewS Sep 27 '14 at 19:38
  • Also, we were given the round prototype as well as the exact function call to use to set change, so being given something and having to use it does not mean I understand it. – MatthewS Sep 27 '14 at 19:41
  • If you got your program to work with the suggested simple fix, you might want to write an alternative version *without* using the type `double` and show it to the person who told you to use it. As well as your reasoning why it should work as good -- if not better. – Jongware Sep 27 '14 at 20:03
  • what I ended up doing is creating another double (changeInDollars) and then used changeInDollars = paid - cost. I then printed out changeInDollars to two decimal places. I get the correct output, so if someone has another suggestion that does not require me to create another variable, then please suggest. Thank you all for your help! – MatthewS Sep 27 '14 at 20:09
  • @user3121023 `printf ("$%d.%02d\n", change/100, change%100)` is OK as long as `change >= 0` but has 2 negative signs with values like `change == -102`. Also tricky with `change = -3`. – chux - Reinstate Monica Sep 27 '14 at 23:48
  • @Jongware Good finical code can be had with `double`. Using `int` helps cope with exactness issues typical first encountered with money, but incurs range and calculation issues later on. Should code use `double`, `int` or [decimal64](http://en.wikipedia.org/wiki/Decimal64_floating-point_format), all have pros, cons and pitfalls with financial coding - none are absolutely better than the other. Proper coding is needed with any type. – chux - Reinstate Monica Sep 28 '14 at 00:00
  • the issue is that I am required to get the input using double, which, unless I'm mistaken, is converted to an int using the round prototype. When you go from double to int you lose the decimal places because, again unless I am mistaken, int is not meant for decimal point values whereas double is. – MatthewS Sep 28 '14 at 00:16
  • OP: When code converts from `double` to `int`, the value fractional part is discarded. If the result does not fit in the range of `int`, the result is "undefined behavior". True: "`int` is not meant for decimal point values whereas `double` is". Sometimes `int` is used for decimal value by _scaling_. Like here, the money is counted in $0.01 units. Code code use $0.0000001 units, etc. Of course the smaller the unit, the smaller the working range of min and max dollar. – chux - Reinstate Monica Sep 28 '14 at 00:23

1 Answers1

0

The key issue is not scaling the change (in cents) when printing (in dollars).

Code can use the print change as an int as suggested by @user3121023, but this has trouble with negative change.

printf ("$%d.%02d\n", change/100, change%100);

or convert to a double

printf("$%.2f\n", change/100.0);

There many issues with financial code, like the weak round(double change) which fails for large or negative values and its bias to round up "half-way" numbers. math.h has a much better round() function.

Another example, rounding should occur on each element of the transaction and possible and with the final amount,

scanf("%lf", &cost);
cost = round(cost * 100.0);

scanf("%lf", &paid);
paid = round(paid * 100.0);

// change = round((paid - cost) * 100.0);
change = round(paid - cost);

Recommend keeping money in 1 type rather than 2 as in

int change, temp; 
double cost, paid;

Using int helps with exactness issues, but has its problem with I/O, range and calculations.

Using double helps with range and calculation, but proper rounding is often needed.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256