2

I just finished my change calculator (Calculates change based on cost of purchase and cash given). I was testing it to see if it works and found one bug. Whenever the amount of pennies to be given is exactly one, it says it is 0. I went through the code and did the math manually off the code I wrote (without running it) and it looks like it should work. If you want to test this yourself just put in 0 as the cost of the purchase and 36.91 as the cash given. (This means the change is 36.91 and it should be 1 twenty, 1 ten, 1 five, 1 half dollar, 1 quarter, 1 dime, 1 nickel, and 1 penny [but it says 0 pennies].

Due note: I am very new to C++ and know VERY little

Here is the code:

/*This program simulates a situation at the register where someone pays with cash
and the cashier needs to know how much change and of which coins he or she needs to give.
Written by Jay Schauer
*/

//Data Declarations
#include <iostream>
#include <cstdint>

int main()
{
    using namespace std;

    double cost; //Stores cost of purchase
    cout << "Input cost of purchase (in USD)" << endl;
    cin >> cost;
    double cash; //Stores cash that pays for purchase
    cout << "Input cash given (in USD)" << endl;
    cin >> cash;
    double changet = cash - cost; //Stores the change,
    the t is for temporaary because I use a different change variable later
    cout << "Change to be given is " << changet << " in..." << endl;

    //Also, I thought this was pretty clever since doubles apparantly can't be used
    //with modulus (it gave me an error),
    //so I figured I just multiply it by 100 and multiply all the divisions by 100 also

    changet *= 100;
    int change = changet; //Converts changet to an integer to be used with the modulus
    int coins; //Stores the amount of "coins" to be given as change

    coins = change / 2000;
    cout << coins << " twenty dollar bills" << endl;
    change = change % 2000;

    coins = change / 1000;
    cout << coins << " ten dollar bills" << endl;
    change = change % 1000;

    coins = change / 500;
    cout << coins << " five dollar bills" << endl;
    change = change % 500;

    coins = change / 100;
    cout << coins << " one dollar bills" << endl;
    change = change % 100;

    coins = change / 50;
    cout << coins << " half dollars" << endl;
    change = change % 50;

    coins = change / 25;
    cout << coins << " quarters" << endl;
    change = change % 25;

    coins = change / 10;
    cout << coins << " dimes" << endl;
    change = change % 10;

    coins = change / 5;
    cout << coins << " nickels" << endl;
    change = change % 5;

    //There is one problem that I can't figure out
    //If the number of pennies to be given for change is exactly 1,
    //it says 0 for the number of pennies to be given as change
    coins = change / 1;
    cout << coins << " pennies" << endl;

    system("pause");
    return 0;
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
Jay Schauer
  • 477
  • 1
  • 5
  • 15

2 Answers2

4

Unfortunately you've stubled across one of the common problems with using double and floating point values. They aren't exact. They are good enough for rock and roll, but when you want exact, wellll....

OK so you have 36.91... sort of. It's really something like 36.90999999999. You multiply it by 100 and get 3690.999999999. You convert it into an integer and get truncated to 3690. The fraction is completely discarded.

You should be able make it work here by rounding .

int change = std::round(changet);
user4581301
  • 33,082
  • 7
  • 33
  • 54
2

This code is relying on integer division, when you should be using floating-point division. In short, you are truncating the decimal portions of your answers.

Let's step through, using your input of $36.91. First, with $20 bills:

  1. coins = change / 2000; -> coins = 3691 / 2000; -> coins = 1.8455;

since we are dealing with integers, this falls into integer division and coins is actually set to 1. One $20 bill is due as change.

Moving on, for $10 bills:

  1. change = change % 2000; -> change = 3691 % 2000; -> change = 1691;
  2. coins = change / 1000; -> coins = 1691 / 1000; -> coins = 1.691;

again, this falls into integer division, so 1.691 is truncated and coins is set to 1. The program will indicate that one $10 bill is due.

Now, for $5 bills...

  1. change = change % 1000; -> change = 1691 % 1000; -> change = 691;
  2. coins = change / 500; -> coins = 691 / 500; -> coins = 1.382;

The decimal component of 1.382 is, again, dropped, and coins is set to 1. That's one $5 bill.

  1. change = change % 500; -> change = 691 % 500; -> change = 191;
  2. coins = change / 100; -> coins = 191 / 100; -> coins = 1.91;

1.91 is truncated to 1. That's one $1 bill.

  1. change = change % 100; -> change = 191 % 100; -> change = 91;
  2. coins = change / 50; -> coins = 91 / 50; -> coins = 1.82;

Again, that's truncated. 1.82 is cast to an integer set to 1. One half-dollar.

  1. change = change % 50; -> change = 91 % 50; -> change = 41;
  2. coins = change / 25; -> coins = 41 / 25; -> coins = 1.64;

One quarter.

  1. change = change % 25; -> change = 41 % 25; -> change = 16;
  2. coins = change / 10; -> coins = 16 / 10; -> coins = 1.6;

One dime.

  1. change = change % 10; -> change = 16 % 10; -> change = 6;
  2. coins = change / 10; -> coins = 6 / 5; -> coins = 1.2;

One nickel.

  1. change = change % 5; -> change = 6 % 5; -> change = 1;
  2. coins = change / 1; -> coins = 1 / 1; -> coins = 0.9999999999999;

Zero pennies.

The reason for this is how binary arithmetic handles division. There is a loss of precision that is causing 0.9999999 to be calculated, which when truncated will result in zero pennies.

Your solution: Since dividing something by 1 yields that same something (identity), take coins = change / 1; out of your program.

Also, search for an article on floating point arithmetic.

contracode
  • 405
  • 2
  • 5
  • 1
    You are correct that floating point math is the issue, but your suggestion is not the ideal one. This is inherently an integer problem. You can't give someone a fractional penny in change. The issue is not how he uses floating point, but that he uses it at all. If he simply changes all doubles to ints, all of the floating point problems go away, and he will get the correct answer. – ThoughtfulHacking Feb 08 '16 at 21:54