We're a community of 1077K IT Pros here for help, advice, solutions, professional growth and fun. Join us!
1,076,124 Members — Technology Publication meets Social Media

# Weird double calculation bug

Hi, I'm writing a simple program that runs a vending machine. I thought I had everything working fine untill I messed around with the money input some more. In my program I obviously compare money values and check to make sure the values match up exactly to buy an item. It works under almost every case, but I have found some cases where I get an anomalous decimal value that throws off the comparison of the double values. Here is my code and output from testing within the money class itself.

``````public class Money {
private static final double NICKEL_AMMNT = 0.05;
private static final double DIME_AMMNT = 0.10;
private static final double QRT_AMMNT = 0.25;

private int numNickels, numDimes, numQrts;

public Money(int numNickels, int numDimes, int numQrts) {
this.numNickels = numNickels;

this.numDimes = numDimes ;

this.numQrts = numQrts ;

}

public int getNickels(){
return numNickels;
}

public int getDimes(){
return numDimes;
}

public int getQrts(){
return numQrts;
}

public double getTotal(){
double total = ((numNickels * NICKEL_AMMNT) + (numDimes * DIME_AMMNT) + (numQrts * QRT_AMMNT));

}

public String toString(){
String tempString = "";
tempString += ("Nickels: "+getNickels()+"\n");
tempString += ("Dimes: "+getDimes()+"\n");
tempString += ("Quarters: "+getQrts()+"\n");
tempString += ("Total Cash: \$"+(getNickels()*NICKEL_AMMNT + getDimes()*DIME_AMMNT + getQrts()*QRT_AMMNT));
return tempString;
}

public static void main(String[] args){
Money money1 = new Money(2, 3, 1);
System.out.println("2 Nickels, 3 Dimes, 1 Quarter");
System.out.println(money1.getTotal()+"\n");

Money money2 = new Money(3, 2, 3);
System.out.println("3 Nickels, 2 Dimes, 3 Quarters");
System.out.println(money2.getTotal()+"\n");

Money money3 = new Money(1,6,0);

System.out.println("1 Nickels, 6 Dimes, 0 Quarters\n"+money3.getTotal());

Money money4 = new Money(3,0,0);
System.out.println("\n3 Nickels,0 Dimes, 0 Quarters\n"
+money4.getTotal());
}

}
``````

The output from this code in main gives me:
2 Nickels, 3 Dimes, 1 Quarter
0.65

3 Nickels, 2 Dimes, 3 Quarters
1.1

1 Nickels, 6 Dimes, 0 Quarters
0.6500000000000001

3 Nickels,0 Dimes, 0 Quarters
0.15000000000000002

It works fine under most cases, but I'm sometimes getting weird results when adding up the values. Can someone explain first why this is occuring, and how to fix it, or foce my double values to be two decimal places?

2
Contributors
3
Replies
12 Hours
Discussion Span
6 Months Ago
Last Updated
4
Views
Question
Yoink
Light Poster
26 posts since Feb 2012
Reputation Points: 10
Skill Endorsements: 0

It's a mistake to use doubles here. Decimal fractions (eg 0.1) can't be exactly represented in a binary floating point format, so rounding errors are inevitable.
Your values are always an exact integer number of cents, so the obvious simplest (correct) way to hold the values in cents, not dollars, and store them in int variables. That way your calculations will always be exactly correct.
You may find it usefulto write a simple little method that takes a valaue in cents and converts it to a display string in \$ddd.cc format, so your printouts are easy and look good.

JamesCherrill
... trying to help
Moderator
8,519 posts since Apr 2008
Reputation Points: 2,583
Skill Endorsements: 30

Thanks, I'll try that and see where it gets me

Yoink
Light Poster
26 posts since Feb 2012
Reputation Points: 10
Skill Endorsements: 0

Here is the fix which I tested and it seems to work fine. Thanks for the tip.

``````public class Money {
//Nickels,Dimes,Qrts stored as number of cents in integers (i.e. NICKEL_AMMNT = 5 is 5 cents)
//values are calculated as dollar amounts in getTotal() method
private static final int NICKEL_AMMNT = 5;
private static final int DIME_AMMNT = 10;
private static final int QRT_AMMNT = 25;

//the number of nickels,dimes,qrts that the user inputs
private int numNickels, numDimes, numQrts;

public Money(){
numNickels = 0;
numDimes = 0;
numQrts = 0;
}

public Money(int numNickels, int numDimes, int numQrts) {
this.numNickels = numNickels;

this.numDimes = numDimes ;

this.numQrts = numQrts ;

}

public int getNickels(){
return numNickels;
}

public int getDimes(){
return numDimes;
}

public int getQrts(){
return numQrts;
}

public double getTotal(){
double nickels = (double)(numNickels * NICKEL_AMMNT)/100;
double dimes = (double)(numDimes * DIME_AMMNT)/100;
double qrts = (double)(numQrts * QRT_AMMNT)/100;
double total = (nickels+dimes+qrts);

}

public String toString(){
String tempString = "";
tempString += ("Nickels: "+getNickels()+"\n");
tempString += ("Dimes: "+getDimes()+"\n");
tempString += ("Quarters: "+getQrts()+"\n");
tempString += ("Total Cash: \$"+getTotal());
return tempString;
}

public static void main(String[] args){
Money money1 = new Money(2, 3, 6);
System.out.println(money1.toString()+"\n"); // toString implements get nickels,dimes,qrts, and getTotal()

Money money2 = new Money(0,1,1);
System.out.println(money2.toString()+"\n");

Money money3 = new Money(7,0,0);
System.out.println(money3.toString()+"\n");

Money money4 = new Money(1,6,0);
System.out.println(money4.toString());

}

}
``````

With the testing output:
Nickels: 3
Dimes: 3
Quarters: 6
Total Cash: \$1.95

Nickels: 0
Dimes: 1
Quarters: 1
Total Cash: \$0.35

Nickels: 7
Dimes: 0
Quarters: 0
Total Cash: \$0.35

Nickels: 1
Dimes: 6
Quarters: 0
Total Cash: \$0.65

Yoink
Light Poster
26 posts since Feb 2012
Reputation Points: 10