1

I have just started learning Java and I can't seem to get this calculator to work. I want to have a variable amount, and from that, calculate the least number of coins needed to make this amount.

This is my program:

double amount, quarters, dimes, nickels, pennies;
int quartersNeeded, dimesNeeded, nickelsNeeded, penniesNeeded;

amount  = 1.63;
quarters = 0.25;
dimes = 0.1;
nickels = 0.05;
pennies = 0.01;

quartersNeeded = (int)(amount / quarters);
amount = amount - (quartersNeeded * 0.25);

dimesNeeded = (int)(amount / dimes);
amount = amount - (dimesNeeded * 0.1);

nickelsNeeded = (int)(amount / nickels);
amount = amount - (nickelsNeeded * 0.05);

penniesNeeded = (int)(amount / pennies);
amount = amount - (penniesNeeded * 0.01);
System.out.println(amount);

System.out.println(quartersNeeded);
System.out.println(dimesNeeded);
System.out.println(nickelsNeeded);
System.out.println(penniesNeeded);

Quarters, dimes, and nickels seem to work fine but once it gets to pennies, the amount is something like 0.0099999999999887 and penniesNeeded is always short one if the hundredth place of the initial amount is 3,4,7,8,9.

Kevin Brechbühl
  • 4,717
  • 3
  • 24
  • 47
  • Ah yes, this issue shows up in Effective Java by Bloch. – Caffeinated Feb 15 '14 at 18:55
  • 4
    This is a floating point number problem, not java specific. If you are just learning java it will be hard to explain thoroughly but its related to the maximum precision of floating point numbers, to solve this you will have to account for the loss of precision – Ryan Feb 15 '14 at 18:55
  • http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – Dave Newton Feb 15 '14 at 18:56
  • Related articles about NOT using doubles when exact answers are needed, and DON'T use them for currency: https://www.securecoding.cert.org/confluence/display/java/NUM04-J.+Do+not+use+floating-point+numbers+if+precise+computation+is+required http://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency https://www.google.com/search?q=exact+answer+do+not+use+double+float+java – aliteralmind Feb 15 '14 at 18:56
  • You can use a [BigDecimal](http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html), and a [MathContext](http://docs.oracle.com/javase/7/docs/api/java/math/MathContext.html) to be as precise as you want. – Elliott Frisch Feb 15 '14 at 18:57
  • The Goldberg article isn't very newbie-friendly. Try http://floating-point-gui.de instead. – yshavit Feb 15 '14 at 18:58

2 Answers2

3

When dealing with currency, you should never use floating point for this reason. Instead, use a integer type for the number of cents:

amount = 163;
final QUARTER = 25;
final DIME = 10;
...
chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
0

The answer is to not use double. It is an IEEE 754 64-bit floating point number, and even such simple decimal values as 0.1 cannot be represented reliably as doubles. Note "decimal": the way we write number is using base 10; with IEEE 754, floating point numbers use base 2.

Use BigDecimal instead. And if you care about performance, use apfloat.

fge
  • 119,121
  • 33
  • 254
  • 329