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));

        return total;
        }

    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?

Recommended Answers

All 3 Replies

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.

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

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);
        return total;

    }

    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

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.