Yesterday I came across a handy loan payment calculator in C# by Jonathon Wood via Alvin Ashcraft’s Morning Dew links. The implementation appears to be idiomatic C# using a class, mutable properties and wrapped in a host console application to display the results.
I thought it’d be fun to spend a few moments re-implementing it in F# so it can be executed in F# interactive as a script or a console application.
Rather than use a class, I’ve plumped for a record type that captures all the required fields:
/// Loan record
type Loan = {
/// The total purchase price of the item being paid for.
PurchasePrice : decimal
/// The total down payment towards the item being purchased.
DownPayment : decimal
/// The annual interest rate to be charged on the loan
InterestRate : double
/// The term of the loan in months. This is the number of months
/// that payments will be made.
TermMonths : int
}
And for the calculation simply a function:
/// Calculates montly payment amount
let calculateMonthlyPayment (loan:Loan) =
let monthsPerYear = 12
let rate = (loan.InterestRate / double monthsPerYear) / 100.0
let factor = rate + (rate / (Math.Pow(rate+1.,double loan.TermMonths) 1.))
let amount = loan.PurchasePrice - loan.DownPayment
let payment = amount * decimal factor
Math.Round(payment,2)
We can test the function immediately in F# interactive
let loan = {
PurchasePrice = 50000M
DownPayment = 0M
InterestRate = 6.0
TermMonths = 5 * 12
}
calculateMonthlyPayment loan
Then a test run (which produces the same results as the original code):
let displayLoanInformation (loan:Loan) =
printfn "Purchase Price: %M" loan.PurchasePrice
printfn "Down Payment: %M" loan.DownPayment
printfn "Loan Amount: %M" (loan.PurchasePrice - loan.DownPayment)
printfn "Annual Interest Rate: %f%%" loan.InterestRate
printfn "Term: %d months" loan.TermMonths
printfn "Monthly Payment: %f" (calculateMonthlyPayment loan)
printfn ""
for i in 0M .. 1000M .. 10000M do
let loan = { loan with DownPayment = i }
displayLoanInformation loan
Another option is to simply skip the record and use arguments:
/// Calculates montly payment amount
let calculateMonthlyPayment(purchasePrice,downPayment,interestRate,months) =
let monthsPerYear = 12
let rate = (interestRate / double monthsPerYear) / 100.0
let factor = rate + (rate / (Math.Pow(rate + 1.0, double months) - 1.0))
let amount = purchasePrice - downPayment
let payment = amount * decimal factor
Math.Round(payment,2