1

I need to create a program that can calculate change in the most efficient way possible. Ex. 3 Quarters instead of 75 pennies. It is only single dollar bills, quarters, dimes, etc. However, there are a few rules i need to follow.

1) Isolate both the dollars and cents components of the original input string into separate sub strings.

2) Use the Integer utility class to parse these two sub strings into primitive integer values.

3) You may not use any typecasting in your work.

4) Test thoroughly to ensure that no rounding errors remain.

The code is what I did initially, but i am always a penny off for some values

public class ChangeCalculator
{
public static void Main (String args[]){
    double NumberOfMoney = Double.parseDouble(args [0]);
    int NumberOfCoins = (int)(NumberOfMoney * 100);

    System.out.println("Amount of Money: " + NumberOfMoney + "\n");

    int NumberOfDollars = (int)(NumberOfCoins/100);
    NumberOfCoins = NumberOfCoins - 100 * NumberOfDollars;
    System.out.println("Dollars: " + NumberOfDollars);

    int NumberOfQuarters = (int)(NumberOfCoins/25);
    NumberOfCoins = NumberOfCoins - 25 * NumberOfQuarters;
    System.out.println("Quarters: " + NumberOfQuarters);

    int NumberOfDimes = (int)(NumberOfCoins/10);
    NumberOfCoins = NumberOfCoins - 10 * NumberOfDimes;
    System.out.println("Dimes: " + NumberOfDimes);

    int NumberOfNickels = (int)(NumberOfCoins/5);
    NumberOfCoins = NumberOfCoins - 5 * NumberOfNickels;
    System.out.println("Nickels: " + NumberOfNickels);

    int NumberOfPennies = (int)(NumberOfCoins/1);
    NumberOfCoins = NumberOfCoins - 1 * NumberOfPennies;
    System.out.println("Pennies: " + NumberOfPennies);
}
}

the input $1.15 should output Dollars: 1 Quarters: 0 Dimes: 1 Nickels: 1 Pennies: 0 BUT it outputs Dollars: 1 Quarters: 0 Dimes: 1 Nickels: 0 Pennies: 4

Andrew Lin
  • 11
  • 1
  • 5
  • "$1.15 should output Dollars: 1 Quarters: 0 Dimes: 1 Nickels: 5 Pennies: 0" Should it not be: "Dollars: 1 Quarters: 0 Dimes: 1 Nickels: 1 Pennies: 0?" – AleksW Apr 09 '19 at 18:29
  • 1
    For your Input, please try printing NumberOfCoins variable first and debug. The initial value of NumberOfCoins is not calculated correctly. – BlackPearl Apr 09 '19 at 18:32
  • @AleksW thanks I edited it – Andrew Lin Apr 10 '19 at 14:30

4 Answers4

2

Try this as your second line in Main:

int NumberOfCoins = (int)Math.round(NumberOfMoney * 100);

The reason this is that NumberOfMoney * 100 is 114.999999999, and so (int)(NumberOfMoney * 100) is 114. In general, you should be careful not to trust the value of double and float variables to be exact.

Cam
  • 14,930
  • 16
  • 77
  • 128
2

The problem here is that double is not as precise as some people may have lead you to believe. In your code, the problem relies on

int NumberOfCoins = (int)NumberOfMoney * 100;

as the output of this operation is 114.999999999... There are 2 options here, you can either round the operation using Math.roundor use another type that is more precise but slower like BigDecimal.

You can use BigDecimal if you want that precision but the basic operators like +,-,/* doesnt exist on BigDecimal but you can use their methods add, multiply, substract, etc.

Update 1:
Code review
Ideally the naming of you variables should start with lowercase and then all the following words, capital letter for the beginning. eg.

NumberOfMoney should be numberOfMoney
NumberOfCoins should be numberOfCoins The names can be improved but that is ok for the moment.

If you divide a int by another int the final value will be always an int there is no need to cast it.
eg

//The following statements are equal
int NumberOfDollars = (int)(NumberOfCoins/100);
int NumberOfDollars = NumberOfCoins / 100;

This operation is overly complicated and you can simplyfy it more

//from
int NumberOfDollars = NumberOfCoins / 100;
NumberOfCoins = NumberOfCoins - 100 * NumberOfDollars;

//to
int NumberOfDollars = NumberOfCoins / 100;
NumberOfCoins = NumberOfCoins % 100;

Update 2:
From the rules that you posted, you are not following rule 1,2 and 3. For rule 1, it is asking you to isolate the 2 components of the String. The first componen is the dollars values and the second one is the cents values.

String amountValue = "1.15";
String dollaralue = "1" // you need to figure out how to do this.
String centValue = "15" // same

For rule 2, check the documentation for Integer and specificly to parseInt.

For rule 3, this is typecasting int NumberOfCoins = (int)(NumberOfMoney * 100);.

1

change your int NumberOfCoins = (int)(NumberOfMoney * 100); to int NumberOfCoins = (int)(Math.round(NumberOfMoney * 100));

As other peers have mentioned double and float can't be really trusted while dealing with currencies, worth reading Why not use Double or Float to represent currency?

Manish Karki
  • 473
  • 2
  • 11
1

The errors you are seeing are related to the fact that you aren't following instruction 3, to avoid type casting.

In several places you do something like:

int NumberOfCoins = (int)(NumberOfMoney * 100);

That's casting, and casting between int and double can cause the rounding errors you are seeing. You can work around this by rounding in particular ways.

However, I think you'd do well to follow the first instruction you have:

1) Isolate both the dollars and cents components of the original input string into separate sub strings.

Then you'll be dealing with integers and can do your calculations more cleanly.

theonlyrao
  • 416
  • 2
  • 13