Skip to content

Project: Mortgage Calculator Pt 2

Let’s go back to our Mortgage calculator and implement some basic error handling

  1. Update our Principal Label to suggest a range of money available to borrow being between $1K - $1M
    1. If the user enters anything below or over the range a message is returned stating Enter a number between 1,000 and 1,000,000 and the Principal input is shown.
  2. The Annual Interest Rate should be updated to only accept a range that is >0 and < 30
    1. If the user enters an invalid number the terminal prints Enter a value greater tan 0 and less than or equal to 30. and the Annual interest rate input is shown.
  3. The Period (Years) should be between 1 and 30
    1. If the user enters an invalid number the terminal prints Enter a value between 1 and 30 and the Annual interest rate input is shown.
  4. Finally our monthly payments are returned.

A reminder on the formula for calculating mortgage payments:

m = Mortgage p = Principal r = Monthly interest rate (r / 100)/12 n = Number of payments (as it’s monthly over 30 years number of months in 30 years.) 30 * 12

$M = P \times \frac{r(1 + r)^n}{(1 + r)^n - 1}$

Math has the pow method Math.pow(a, b) where it takes the value of one and provides a power of to the second one.

import java.text.NumberFormat;
import java.util.Scanner;
public class MortgageCalculator {
    public static void main(String[] args) {
        final byte MONTHS_IN_YEAR = 12;
        final byte PERCENT = 100;
        Scanner scanner = new Scanner(System.in);
        int principal;
        while(true){
            System.out.print("What is your principal loan amount: ");
            principal = scanner.nextInt();
            if (principal > 1000000 || principal < 1000){
                System.out.println("Enter a number between 1,000 and 1,000,000");
            }
            else {
                break;
            }
        }
        float annualInterestRate;
        while (true){
            System.out.print("What is your annual interest rate: ");
            // Interest rates are usually small numbers so float should be sufficient instead of double
            annualInterestRate = scanner.nextFloat();
            if (annualInterestRate <= 0 || annualInterestRate > 30){
                System.out.println("Enter a value greater than 0 and less than or equal to 30");
            }
            else{
                break;
            }
        }
        float monthlyInterestRate = (annualInterestRate / PERCENT) / MONTHS_IN_YEAR;
        byte yearsLoaned;
        while(true){
            System.out.print("How many years is the loan: ");
            yearsLoaned = scanner.nextByte();
            if(yearsLoaned < 1 || yearsLoaned > 30){
                System.out.println("Enter a value between 1 and 30");
            } else {
                break;
            }
        }
        int numberOfPayments = yearsLoaned * 12;
final int P = principal;
        final float R = monthlyInterestRate;
        final int N = numberOfPayments;
        final double M = P * (R*Math.pow((1+R),N))/(Math.pow((1+R),N)-1);
        NumberFormat currency = NumberFormat.getCurrencyInstance();
        final String RESULT = currency.format(M);
        System.out.println(RESULT);
    }
}
  • Scoped variables needed to be refactored to be accessed outside while loops.
  • Each scope error handler needed it’s own while loop
  • It was important to be verbose in our bounds or else unexpected errors occurred.

The code review with Mosh was aligned to my code structure and reaffirmed our scoped variables approach. The key learning I took from Mosh’s example was to group our scoped variables at the top of our main code block (particularly if they are used multiple times to make it easier to read for reviewers).

import java.text.NumberFormat;
import java.util.Scanner;
public class MortgageCalculator {
    public static void main(String[] args) {
        final byte MONTHS_IN_YEAR = 12;
        final byte PERCENT = 100;
        int principal;
        float annualInterestRate;
        byte yearsLoaned;
        Scanner scanner = new Scanner(System.in);
        while(true){
            System.out.print("What is your principal loan amount: ");
            principal = scanner.nextInt();
            if (principal > 1000000 || principal < 1000){
                System.out.println("Enter a number between 1,000 and 1,000,000");
            }
            else {
                break;
            }
        }
        while (true){
            System.out.print("What is your annual interest rate: ");
            annualInterestRate = scanner.nextFloat();
            if (annualInterestRate <= 0 || annualInterestRate > 30){
                System.out.println("Enter a value greater than 0 and less than or equal to 30");
            }
            else{
                break;
            }
        }
        while(true){
            System.out.print("How many years is the loan: ");
            yearsLoaned = scanner.nextByte();
            if(yearsLoaned < 1 || yearsLoaned > 30){
                System.out.println("Enter a value between 1 and 30");
            }
            else {
                break;
            }
        }
        int numberOfPayments = yearsLoaned * 12;
        float monthlyInterestRate = (annualInterestRate / PERCENT) / MONTHS_IN_YEAR;
        final int P = principal;
        final float R = monthlyInterestRate;
        final int N = numberOfPayments;
        final double M = P * (R*Math.pow((1+R),N))/(Math.pow((1+R),N)-1);
        NumberFormat currency = NumberFormat.getCurrencyInstance();
        final String RESULT = currency.format(M);
        System.out.println(RESULT);
    }
}