0

The program is meant to convert a USD($) quantity inputted by the user (from $0 to $10 max) and output it in quantities of quarters, dimes, nickles, and pennies.

I am currently using:

  • Linux ParrotOS with Geany 1.37.1
  • G++ Compile commands: g++ -std=c++20 -Wall -c "%f"

#include <iostream>

const double QUARTER {0.25};
const double DIME {0.10};
const double NICKLE {0.05};
const double PENNY {0.01};

void dollarToCoin(double cash, unsigned short& quarters, unsigned short& dimes, unsigned short& nickles, unsigned short& pennies){
    
    double cashRemainder = cash;
    quarters = cashRemainder / QUARTER;
    cashRemainder -= QUARTER * quarters;
    dimes = cashRemainder / DIME;
    cashRemainder -= DIME * dimes;
    nickles = cashRemainder / NICKLE;
    cashRemainder -= NICKLE * nickles;
    pennies = cashRemainder / PENNY;
    cashRemainder -= PENNY * pennies;
    std::cout << "Remaining cash: " << cashRemainder << '\n';

}

int main(){
    
    double cash{0};
    unsigned short quarters{0};
    unsigned short dimes{0};
    unsigned short nickles{0};
    unsigned short pennies{0};
    
    std::cout << "Input your cash ($0 - $10 max): ";
    std::cin >> cash;
    dollarToCoin(cash, quarters, dimes, nickles, pennies);
    
    std::cout << "Total quarters: " << quarters <<
    '\n' << "Total dimes: " << dimes <<
    '\n' << "Total nickles: " << nickles << 
    '\n' << "Total pennies: " << pennies << '\n';
    

    return 0;
}

The offending line is nickles = cashRemainder / NICKLE; in the dollarToCoin() function. here is the pseudocode:

  1. Starting the program, I input 1.2 as an example
  2. In the dollarToCoin() we copy the cash (1.2 dollars) into the cashRemainder
  3. We calculate quarters by dividing cashRemainder (1.2) / QUARTER (0.25) = 4.8 we save only the integer and lose the .8 (now we have 4 quarters = $1.00)
  4. We substract those 4 quarters to the cashRemainder (1.2) giving out 0.2
  5. This is my confusion part: we calculate total of times dimes = cashRemainder(0.2) / DIME (0.1) if I debug this part, it output 1 instead of 2.

If I, however, replace dimes = cashRemaindder / DIME by using --> dimes = 0.2 / DIME this actually outputs 2.

At the end of the program it should convert the input (1.2) into:

Quarters: 4, Dimes: 2, Nickles: 0, Pennies: 0

I still haven't optimized the code nor used any libraries (by which I know there are easier ways) I'm just confused as why this happening.

  • 5
    It's worthwhile to note that it's not usually advisable to represent exact denominations of cash values using floating-point. Floating point is an approximation, and there are many numbers that it represent exactly unlike with decimal values -- which may lead to small margins of error that can lead to incorrect computations. Not saying this is the reason to the problem, but it's something to be aware of. – Human-Compiler Feb 13 '21 at 17:36
  • 3
    Please find the exact point in your program where variables start having other valies than you expect. And identify it in your questions code. It is unlikely that it is the line you point out, being the third of three very similar lines. – Yunnosch Feb 13 '21 at 17:37
  • 3
    The result of `cashRemainder / DIME` is probably something like `1.999999999`. By assigning that floating-point number to an integer, you are truncating the result to `1`. – Andreas Wenzel Feb 13 '21 at 17:43
  • 3
    I totally agree with the duplicate here, but just to metion what exactly breaks: 4. _"We substract those 4 quarters to the cashRemainder (1.2) giving out 0.2"_ - due to floating point math the result is 0.19999999999999996. Divide that by 0.2 and the result is just shy of 2. More like 1.99999.... Truncation results in 1. – Lukas-T Feb 13 '21 at 17:43
  • 1
    The problem most likely is that `dimes = cashRemainder / DIME` is assigning a floating point result to `dimes`, which is an `unsigned short`. Assignment to integer values **truncates** the value -- so any accumulated error levels (as I mentioned above) may result in a value that is close to, but not exactly, 2 -- such as `1.99999999` which will truncate to `1` on assignment. The best solution would be to only use integral values for this; but you could also potentially fix your problem with `std::round` (**Edit:** churill apparently beat me to it) – Human-Compiler Feb 13 '21 at 17:47
  • 1
    as others have said don't use floating point at all here, use integers as cents rather than floating point as dollars, e.g.: https://godbolt.org/z/s1bo9o – Alan Birtles Feb 13 '21 at 17:50
  • Floating point is an *approximation*. All powers of `0.1` (`0.1`, `0.01`, etc) *cannot* be represented exactly in floating point (with a binary mantissa). Most multiples and sums of multiples of those values also cannot be exactly represented (e.g. `0.11`, `0.12`). There are relatively few exceptions (e.g. multiples of `0.25` can be represented). Operations involving inexact values do not necessarily give exact values - so the errors propagate. This is why floating point is an extremely BAD choice to represent currency. – Peter Feb 13 '21 at 20:53

0 Answers0