2

I am creating a simple app in Angular that calculates loan payments. To calculate the monthly payment I have to deal with a pretty small number.

I tried using the "Big" library to no avail as I didn't really understand how it worked. Typescript only has one "number" type so using a number with more memory is out of the question I assume.

Here is the code:

calcDisFac(i: number, n: number) {
    console.log(i);
    console.log(n);

    const firstTerm = Math.pow((1 + i), n) - 1;
    console.log(firstTerm);
    const secondTerm = Math.pow((i * (1 + i)), n);
    console.log(secondTerm);
    return firstTerm / secondTerm;
}

Use the example case where i = (7.75 / 100) / 12 and n = 360

The expected output is 3300 or somewhere around there and the problem is the number is so small it just becomes 0. Any help is appreciated.

MaxAttax
  • 67
  • 6
  • It looks like `secondTerm` is going to be very very close to 0 if it's truly supposed to be (i+i²)ⁿ when i is small is n is large. I strongly suspect you're doing the wrong calculation and that the floating point precision is not your issue. What is the actual formula you're supposed to be calculating? – jcalz Jul 11 '19 at 02:43
  • "Typescript only has one "number" type". There is `BigInt`, though I don't think it's designed for small numbers. – pathurs Jul 11 '19 at 03:11
  • 1
    can i have your formula – Chanaka Weerasinghe Jul 11 '19 at 04:19
  • I think the only acceptable answer for this question will either be source code that looks a lot like a precision math library, or answer that uses a precision math library. There is not short cut solution here, and I think you can just use Google to find a library that you like as we can not recommend one for you. – Reactgular Jul 11 '19 at 07:10

1 Answers1

1

Here is the answer you get when you perform your calculation for secondTerm with WolframAlpha, which will use symbolic computation where necessary to achieve greater precision than JavaScript's floating point math: 4.46531771441003×10^-788. That number is so close to zero that it should be a warning sign to you that something is probably wrong with your calculation.

The result coming out of calcDisFac((7.75 / 100) / 12, 360) would be something like 2.049241445165735×10^788 which, while technically not infinite, is close enough when it comes to something like a monthly payment. It's certainly significantly larger than 3300 of anything I have in my wallet, including atoms.

Backing up... the math you are doing does not calculate loan payments for any type of loan I've ever seen. You can derive the formula yourself for a fixed-rate loan with fixed monthly payments and an initial balance, or you can get it from somewhere like Wikipedia's article on mortgage calculators. I think it would look something like:

function loanPayment(
  initialBalance: number,
  interestRatePerPeriod: number,
  numberOfPayments: number
) {
  const accrual = Math.pow(1 + interestRatePerPeriod, numberOfPayments);
  const paymentRatio = (interestRatePerPeriod * accrual) / (accrual - 1);
  return paymentRatio * initialBalance;
}

JavaScript's floating point math should be more than adequate to handle this calculation for reasonable values of initialBalance, interestRatePerPeriod, and numberOfPayments. And note that you do need an initial balance for the math to make any sense (the payment will be proportional to the initial balance).

So, working backwards from the desired result of 3300, if the initial balance of the loan is something like 460000 then you get:

console.log(loanPayment(460000, 7.75 / 100 / 12, 360)); /// 3295.496

Does that help? Good luck!

Link to code

jcalz
  • 264,269
  • 27
  • 359
  • 360