Choose the right types
You used double
for the coin types, for example:
System.out.println("How many quarters do you have?");
double quarters = keyboard.nextDouble();
quarters = quarters * (0.25);
To the question "how many quarters ...",
it's logical to get an integer (whole number) as the answer, not a double
.
I can guess that you choose the double
type because you want to use the quarters
variable for two different purposes:
- Count the quarters
- Count the dollar value of the quarters
These are conflicting meanings, and the right thing to do is to not mix them,
for example:
int quarters = keyboard.nextInt();
double dollarValueOfQuarters = quarters * .25;
The Single Responsibility Principle
The main
is doing too much: it has too many responsibilities:
- Calculate the dollar value of coins
- Calculate the compound interest
It would be better to split the method into, and give them a name according to their main responsibility, for example:
private static void calculateDollarValueOfCoins(Scanner scanner, NumberFormat moneyFormat) { ... }
private static void calculateCompoundInterest(Scanner scanner, NumberFormat moneyFormat) { ... }
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
NumberFormat moneyFormat = NumberFormat.getCurrencyInstance();
calculateDollarValueOfCoins(scanner, moneyFormat);
calculateCompoundInterest(scanner, moneyFormat);
}
Now the responsibilities are clearly separated.
I also renamed some variables to better match their purposes:
scanner
instead of keyboard
, because you don't really "scan" things from a keyboard. A scanner is a more abstract concept than a keyboard: for all you care, the input values could come as radio signals from the moon, as long as it implements the Scanner's API, your method can work.
moneyFormat
instead of priceFormat
, which works for both responsibilities nicely: the dollar value of your coins is certainly not a "price", and the worth of your investment is not exactly a "price". They are both about money, and formatting money, so this more general name seems appropriate.
Modeling coins
It might be a good idea to model coins using an enum:
enum Coin {
NICKLE(.05),
DIME(.1),
QUARTER(.25);
private final double value;
Coin(double value) {
this.value = value;
}
}
And to add a helper class for adding coins:
private static class CoinAdder {
private double value = 0;
CoinAdder addCoins(Coin coin, int number) {
value += coin.value * number;
return this;
}
public double getValue() {
return value;
}
}
This way, the calculateDollarValueOfCoins
method I suggested above can be implemented in a somewhat more natural way,
and without embedding the dollar value of coins in it:
private static void calculateDollarValueOfCoins(Scanner scanner, NumberFormat moneyFormat) {
System.out.println("How many quarters do you have?");
int quarters = scanner.nextInt();
System.out.println("How many dimes do you have?");
int dimes = scanner.nextInt();
System.out.println("How many nickles do you have?");
int nickles = scanner.nextInt();
double total = new CoinAdder()
.addCoins(Coin.QUARTER, quarters)
.addCoins(Coin.DIME, dimes)
.addCoins(Coin.NICKLE, nickles)
.getValue();
System.out.println("You have: " + moneyFormat.format(total));
}
Now we have separated the responsibilities even further:
calculateDollarValueOfCoins
doesn't know anymore the value of the different types of coins, and it doesn't know how to add them.
Those responsibilities are delegated to the Coin
enum and the CoinAdder
class,
which is a good thing.
Quick tips
Instead of this:
quarters = quarters * (0.25);
Better:
quarters *= 0.25;
You can write 0.25
as .25
.
You can write 5.
instead of (double) 5
.
Suggested implementation
Putting the above suggestions together, something like this would be better:
class InterestCalculator {
enum Coin {
NICKLE(.05),
DIME(.1),
QUARTER(.25);
private final double value;
Coin(double value) {
this.value = value;
}
}
private static class CoinAdder {
private double value = 0;
CoinAdder addCoins(Coin coin, int number) {
value += coin.value * number;
return this;
}
public double getValue() {
return value;
}
}
private static void calculateDollarValueOfCoins(Scanner scanner, NumberFormat moneyFormat) {
System.out.println("How many quarters do you have?");
int quarters = scanner.nextInt();
System.out.println("How many dimes do you have?");
int dimes = scanner.nextInt();
System.out.println("How many nickles do you have?");
int nickles = scanner.nextInt();
double total = new CoinAdder()
.addCoins(Coin.QUARTER, quarters)
.addCoins(Coin.DIME, dimes)
.addCoins(Coin.NICKLE, nickles)
.getValue();
System.out.println("You have: " + moneyFormat.format(total));
}
private static void calculateCompoundInterest(Scanner scanner, NumberFormat moneyFormat) {
System.out.println("What is the initial investment?");
double investment = scanner.nextDouble();
System.out.println("At what intrest rate is the intrest compounded annually?");
double intrestRate = scanner.nextDouble();
double futureValueFive = investment * Math.pow(1 + intrestRate, 5.);
System.out.println("In five years the investment will be worth : " + moneyFormat.format(futureValueFive));
double futureValueTen = investment * Math.pow(1 + intrestRate, 10.);
System.out.println("In ten years the investment will be worth : " + moneyFormat.format(futureValueTen));
double futureValueTwenty = investment * Math.pow(1 + intrestRate, 20.);
System.out.println("In twenty years the investment will be worth : " + moneyFormat.format(futureValueTwenty));
}
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
NumberFormat moneyFormat = NumberFormat.getCurrencyInstance();
calculateDollarValueOfCoins(scanner, moneyFormat);
calculateCompoundInterest(scanner, moneyFormat);
}
}