3
\$\begingroup\$

I am trying to figure out a more efficient way of converting money into change. The code below is what i have written so far. It works perfectly but i know the code can be improved. Is there a more efficient way of writing this code?

public class Problem2 {

    public static int quarters(int total)
    {
        return total/25;
    }

    public static int dimes(int total)
    {
        return (total - quarters(total)*25) /10;
    }

    public static int nickels(int total)
    {
        return (total - (quarters(total)*25) - (dimes(total)*10)) / 5;
    }

    public static int pennies(int total)
    {
        return total - (quarters(total)*25) - (dimes(total)*10) - (nickels(total)*5);
    }

    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);
        String total;
        int intTotal;
        System.out.println("Hi, this application will take your number and will display the minimum amount of"
                + "coins necessary to represent the dollar amount");
        System.out.println("Please enter in the total amount of dollars and cents:");
        total = keyboard.next();

        total = total.replace(".","");
        intTotal = Integer.parseInt(total);

        System.out.println(quarters(intTotal) + " Quarters," 
                          +dimes(intTotal) + " Dimes,"
                          +nickels(intTotal) + " Nickels,"
                          +pennies(intTotal) + " Pennies");

    }

}
\$\endgroup\$
  • \$\begingroup\$ I'm not certain I understand why a change maker would take change as input, so would you post your requirements? \$\endgroup\$ – Legato Jan 27 '16 at 1:49
  • \$\begingroup\$ So for example: if i input 20.32, it should spit back 81 quarters, 0 dimes, 1 nickel and 2 pennies. I'm sorry if the variable and method naming is off in the program, i'm currently just trying to see if i can get it to run more efficiently before i give the variables a more suitable name \$\endgroup\$ – calvin phung Jan 27 '16 at 3:03
  • \$\begingroup\$ Possibly related: codereview.stackexchange.com/questions/88238/… \$\endgroup\$ – h.j.k. Jan 27 '16 at 11:16
3
\$\begingroup\$

Minor tweak

    public static int pennies(int total)
    {
        return total - (quarters(total)*25) - (dimes(total)*10) - (nickels(total)*5);
    }

A shorter version of this would be

    public static int pennies(int total)
    {
        return total % 5;
    }

Of course, it would be reasonable to argue that the consistency of the original outweighs the terseness of this version.

Don't forget and repeat work

I would also consider making this an object rather than a static class. Then you wouldn't have to recalculate these every time that you wanted one.

And this may be a little too much single responsibility principle. Consider

    public void initialize(int total) {
        quartersCount = total / QUARTER_VALUE;
        total %= QUARTER_VALUE;

        dimesCount = total / DIME_VALUE;
        total %= DIME_VALUE;

        nickelsCount = total / NICKEL_VALUE;
        total %= NICKEL_VALUE;

        penniesCount = total;
    }

This is DRYer, as it puts the change breakdown in just one place rather than doing total - (quarters(total)*25) in three different methods.

A good compiler should generally be able to find the quotient and remainder in one operation, so this should simplify to three calculations even though there are seven assignments. Your original version takes nineteen just to count pennies. Thirty-three to calculate all four. Even if subtractions and multiplications are lower weight than divisions, seven of those were divisions.

I added the constants, as they make it less likely that you will divide by one value and take the remainder of a different value.

I won't write out the getters or the object field declarations.

Just-in-time declarations

        String total;
        int intTotal;
        System.out.println("Hi, this application will take your number and will display the minimum amount of"
                + "coins necessary to represent the dollar amount");
        System.out.println("Please enter in the total amount of dollars and cents:");
        total = keyboard.next();

        total = total.replace(".","");
        intTotal = Integer.parseInt(total);

In Java, it's more customary to do variable declarations just in time to be used. So

        System.out.println("Hi, this application will take your number and will display the minimum amount of"
                + "coins necessary to represent the dollar amount");
        System.out.println("Please enter in the total amount of dollars and cents:");
        String total = keyboard.next();

        total = total.replace(".","");
        int intTotal = Integer.parseInt(total);
\$\endgroup\$
  • \$\begingroup\$ One quick question actually, if you don't mind. Would you mind telling me what total %= QUARTER_VALUE; and total %= DIME_VALUE does? I've never used the assignment "%=" before. Thank you!! \$\endgroup\$ – calvin phung Jan 27 '16 at 18:00
  • \$\begingroup\$ It's a shorter version of total = total % QUARTER_VALUE;. tutorialspoint.com/java/java_assignment_operators_examples.htm \$\endgroup\$ – mdfst13 Jan 27 '16 at 22:56
2
\$\begingroup\$

A few notes:

  • All the operations performed by the methods can be reduced down into modulus % and integer division / operations which can be performed in sequence.

  • You don't have to accept a string from the input every time; the Scanner object has the capability to scan for the next Double, Integer, etc. value in the input.

  • It's confusing to those reading your code when you perform a mathematical operation on a string somewhere in your main method rather than with the rest of your mathematics. Keep general operations grouped.

    • Note that removing a decimal place could easily lead to bugs as it actually represents multiplying the given number by \$10^X\$ where \$X\$ is the number of digits after your decimal place. This is not what you want to do if your intention is to round to the nearest hundredth decimal place.
  • Please include your imports in your source, even if it's just one.

  • Consider implying more directly that the dollar value they entered converts into the given change.

  • Consider using an array to store the exact change.

Making the changes listed above, and compressing the retrieval of change down into one function, the code becomes this:

import java.util.Scanner;

public class Problem2 {

    /**
     * Takes a dollar amount, represented by a double value,
     * and returns the minimum number of quarters, dimes,
     * nickels, and pennies that would be required to
     * represent that dollar value.
     * @param dollarValue
     * @return {Quarters, Dimes, Nickels, Pennies}
     */
    public static int[] getChange(double dollarValue)
    {
        int cents = (int) Math.round(dollarValue*100);
        // Convert the cents into quarters, dimes, nickels, and pennies, respectively.
        int[] change = {cents/25,(cents%=25)/10, (cents%=10)/5, cents%5};
        return change;
    }

    public static void main(String[] args) {
        // Instantiate Variables \\
        double  total;
        int[]   change;
        Scanner keyboard;

        // Receive Input \\
        keyboard = new Scanner(System.in);
        System.out.println("This application calculates the exact change for a given dollar amount.");
        System.out.println("Please enter in the total amount of dollars and cents:");
        total = keyboard.nextDouble();
        keyboard.close();

        // Make Calculations \\
        change = getChange(total);
        System.out.printf("$%.2f = "
                         + change[0] + " Quarters, " 
                         + change[1] + " Dimes, "
                         + change[2] + " Nickels, "
                         + change[3] + " Pennies", total);



    }

}
\$\endgroup\$
  • \$\begingroup\$ @mdfst13 In this simple case, it's just one Scanner, but for more complex code I really do appreciate having the imports there so that I don't have to track down which packages are involved. \$\endgroup\$ – 200_success Jan 27 '16 at 7:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.