Reputation: 15
So I am currently reading a book on learning java and a program outlined inside the book is giving me some trouble. Specifically when I run the program to compute the amount of dollars and change that I should have from 9.87, I get change from what I would get as if I typed 9.86. However when I type 9.86 I get the correct amount of change. As far as I know this only happens with some amounts that end in .87 such as 8.87, although it works for 6.87 fine. This is the book introduction to java programming 8th edition and since it was a book that was written by a professional I am confused as to what the error could be. I have tried running it in cmd and eclipse and both seem to show the fault.
PasteBin Link:
Upvotes: 0
Views: 144
Reputation: 308733
I'm almost certain that you're being bitten by a poor understanding of how floating point numbers work. You can no more represent 0.1 exactly in binary any more than you can 1/3 in decimal. Then, on top of that, IEEE floating point numbers can't have more than 17 digits of precision for doubles.
It's not a bug in Java or your code.
Money is a classic example of something that shouldn't be represented with decimal numbers.
Write a Money class with integer dollars and cents and use that when you learn enough Java:
public class Money {
private final int dollars;
private final int cents;
private final Currency currency;
public Money(int dollars, int cents, Currency curr) {
if (dollars < 0) throw new IllegalArgumentException("dollars cannot be negative");
if (cents < 0) throw new IllegalArgumentException("cents cannot be negative");
if (curr == null) throw new IllegalArgumentException("currency cannot be null");
this.dollars = dollars;
this.cents = cents;
this.currency = curr;
}
// more methods here.
}
Upvotes: 5
Reputation: 372
Try setting amount to 9.87 and then multiplying it with 100:
double amount=9.87;
System.out.println(amount*100);
After that, try printing the same thing, but cast it to int:
double amount=9.87;
System.out.println((int)amount*100);
Casting to int just removes the decimals at the end (as Hot Licks said in the comment) and because you can't represent floating point numbers exactly (as duffymo said in the answer) you end up with 986 instead of 987 as you have expected.
Upvotes: 0
Reputation: 53
duffymo is right. 9.87 x 100 in float might be 986.999999999... which is converted to 986 when casted back to an integer.
You could probably use Math.round() before typecasting using (int) to round the float to the nearest whole number.
import java.lang.Math;
...
int remainingAmount = (int)(Math.round(amount * 100));
...
Produces the correct output :
Your amount 9.87 consists of
9 dollars
3 quarters
1 dimes
0 nickels
2 pennies
Regards,
Manny
Upvotes: 0