import java.util.Scanner; /********************************************************************* * @author Duncan Buell * * written: 26 February 2008 **/ public class Loan2 { private int duration; private double payment,principal,rate; /********************************************************************* * This is the standard constructor, which ought for good form to * explicitly initiale the instance variables for the class. **/ public Loan2() { this.duration = 0; this.principal = 0.0; this.rate = 0.0; } // public Loan2() /********************************************************************* * accessor methods for the instance variables **/ /********************************************************************* * This method simply returns the number of months that is the * duration of the loan. * * @return The int number of months that is the loan duration. **/ public int getDuration() { return(this.duration); } /********************************************************************* * This method simply returns the double precision value of the * current loan payment. * * @return The double value that is the current loan payment. **/ public double getPayment() { return(this.payment); } /********************************************************************* * This method simply returns the double precision value of the * current loan principal. * * @return The double value that is the current loan principal. **/ public double getPrincipal() { return(this.principal); } /********************************************************************* * This method simply returns the double precision value of the loan * interest rate. * * @return The double value that is the loan interest rate. **/ public double getRate() { return(this.rate); } /********************************************************************* * mutator methods for the instance variables **/ /********************************************************************* * This method takes an input string, converts to a integer, and sets * that int value as the number of months duration of the loan. * It SHOULD be the case that extensive error testing is done in this * method to determine that in fact the input string represents a * legal value for a int. However, we don't do that here. * * @param The (String) value of what is supposed to be a int. * @return A boolean false if the input was illegal, else true. **/ public boolean setDuration(String inString) { boolean returnValue; int convertedValue; convertedValue = Integer.valueOf(inString); returnValue = false; if(convertedValue > 0) { this.duration = convertedValue; returnValue = true; } return(returnValue); } // public boolean setDuration(String inString) /********************************************************************* * This method takes an input string, converts to a double, and sets * that double value as the payment per month of the loan. * Same comments about error checking as for the payment. * * @param The (String) value of what is supposed to be a double. * @return A boolean false if the input was illegal, else true. **/ public boolean setPayment(String inString) { boolean returnValue; double convertedValue; convertedValue = Double.valueOf(inString); returnValue = false; if(convertedValue > 0.0) { this.payment = convertedValue; returnValue = true; } return(returnValue); } // public boolean setPayment(String inString) /********************************************************************* * This method takes an input string, converts to a double, and sets * that double value as the prinicpal amount of the loan. * Same comments about error checking as for the payment. * * @param The (String) value of what is supposed to be a double. * @return A boolean false if the input was illegal, else true. **/ public boolean setPrincipal(String inString) { boolean returnValue; double convertedValue; convertedValue = Double.valueOf(inString); returnValue = false; if(convertedValue > 0.0) { this.principal = convertedValue; returnValue = true; } return(returnValue); } // public boolean setPrincipal(String inString) /********************************************************************* * This method takes an input string, converts to a double, and sets * that double value as the interest rate of the loan. * Same comments about error checking as for the payment. * * @param The (String) value of what is supposed to be a double. * @return A boolean false if the input was illegal, else true. **/ public boolean setRate(String inString) { boolean returnValue; double convertedValue; convertedValue = Double.valueOf(inString); returnValue = false; if(convertedValue > 0.0) { this.rate = convertedValue; returnValue = true; } return(returnValue); } /********************************************************************* * general methods **/ /********************************************************************* * This method amortizes the loan until the principal balance is zero. * NOTE: This assumes monthly calculation of interest, without regard * to the number of days in a month, etc. **/ public double amortize(double payment) { double interestThisMonth,localOldPrincipal,localNewPrincipal; localOldPrincipal = this.getPrincipal(); localNewPrincipal = localOldPrincipal; System.out.printf("Mon OldPrinc Int Payment NewPrinc%n"); for(int month = 1; month < this.getDuration(); ++month) { interestThisMonth = localOldPrincipal * (this.rate/100.0) / 12.0; localNewPrincipal = localOldPrincipal + interestThisMonth - payment; System.out.printf("%3d %8.2f %8.2f %8.2f %8.2f %n", month,localOldPrincipal,interestThisMonth, payment,localNewPrincipal); localOldPrincipal = localNewPrincipal; } // for(int month = 1; month < this.getDuration(); ++month) return localNewPrincipal; } // public double amortize() /********************************************************************* * This method computes the payment per month by the time honored * method of BFI (Brute Force and Ignorance). **/ public void computePayment() { final double TOLERANCE = 10.0; boolean closeEnough; double payment,residual,tooLargePayment,tooSmallPayment; tooSmallPayment = 0.0; tooLargePayment = this.getPrincipal(); payment = (tooSmallPayment + tooLargePayment) / 2.0; closeEnough = false; while(!closeEnough) { residual = this.amortize(payment); if(Math.abs(residual) < TOLERANCE) { closeEnough = true; } else { if(residual < 0.0) { tooLargePayment = payment; payment = (tooSmallPayment + tooLargePayment) / 2.0; } else { tooSmallPayment = payment; payment = (tooSmallPayment + tooLargePayment) / 2.0; } } } // while(!closeEnough) } // public void computePayment() /********************************************************************* * This method gets the data and checks that the values are legal. **/ public boolean getGoodData(Scanner console) { boolean goodData; String inputString; System.out.printf("Input loan principal in dollars: "); inputString = console.next(); goodData = this.setPrincipal(inputString); if(false == goodData) { System.out.println("ERROR: input value " + inputString + " is not valid for the principal"); return false; } else { System.out.println("Loan principal is: " + this.getPrincipal()); } System.out.printf("Input loan rate (input '5' for '5.0%%'): "); inputString = console.next(); goodData = this.setRate(inputString); if(false == goodData) { System.out.println("ERROR: input value " + inputString + " is not valid for the rate"); return false; } else { System.out.println("Loan rate is: " + this.getRate()); } System.out.printf("Input loan duration in months: "); inputString = console.next(); goodData = this.setDuration(inputString); if(false == goodData) { System.out.println("ERROR: input value " + inputString + " is not valid for the duration"); System.exit(0); } else { System.out.println("Duration in months is: " + this.getDuration()); } return true; } // public boolean getGoodData(Scanner console) } // public class Loan2