Функция Excel RATE в JS ломается после того, как значения становятся слишком высокими - PullRequest
0 голосов
/ 24 октября 2019

Скрипт сильфона работает точно до тех пор, пока комбинация paymentAmount / futureValue не станет слишком высокой, тогда он рассчитывает его полностью неверно.

export function rate(paymentsPerYear, paymentAmount, presentValue, futureValue, dueEndOrBeginning, interest)
{
  //If interest, futureValue, dueEndorBeginning was not set, set now
  if (interest == null)
    interest = 0.01;

  if (futureValue == null)
    futureValue = 0;

  if (dueEndOrBeginning == null)
    dueEndOrBeginning = 0;

  var FINANCIAL_MAX_ITERATIONS = 1280;//Bet accuracy with 128
  var FINANCIAL_PRECISION = 0.0000001;//1.0e-8

  var y, y0, y1, x0, x1 = 0, f = 0, i = 0;
  var rate = interest;
  if (Math.abs(rate) < FINANCIAL_PRECISION)
  {
    y = presentValue * (1 + paymentsPerYear * rate) + paymentAmount * (1 + rate * dueEndOrBeginning) * paymentsPerYear + futureValue;
  }
  else
  {
    f = Math.exp(paymentsPerYear * Math.log(1 + rate));
    y = presentValue * f + paymentAmount * (1 / rate + dueEndOrBeginning) * (f - 1) + futureValue;
  }
  y0 = presentValue + paymentAmount * paymentsPerYear + futureValue;
  y1 = presentValue * f + paymentAmount * (1 / rate + dueEndOrBeginning) * (f - 1) + futureValue;

  // find root by Newton secant method
  i = x0 = 0.0;
  x1 = rate;
  while ((Math.abs(y0 - y1) > FINANCIAL_PRECISION)
  && (i < FINANCIAL_MAX_ITERATIONS))
  {
    rate = (y1 * x0 - y0 * x1) / (y1 - y0);
    x0 = x1;
    x1 = rate;

    if (Math.abs(rate) < FINANCIAL_PRECISION)
    {
      y = presentValue * (1 + paymentsPerYear * rate) + paymentAmount * (1 + rate * dueEndOrBeginning) * paymentsPerYear + futureValue;
    }
    else
    {
      f = Math.exp(paymentsPerYear * Math.log(1 + rate));
      y = presentValue * f + paymentAmount * (1 / rate + dueEndOrBeginning) * (f - 1) + futureValue;
    }

    y0 = y1;
    y1 = y;
    ++i;
  }
  return rate;
}

Рабочий и нерабочий пример с немного отличающимися входами можно найти здесь: https://jsbin.com/ziluwup/edit?js,console

Есть идеи?

РЕДАКТИРОВАТЬ: Как предложено в комментарии, я добавил правильный результат (0,005420910) в пример на jsbin.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...