用PHP计算利率 [英] Calculating interest rate in PHP

查看:172
本文介绍了用PHP计算利率的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在给定初始贷款金额,还款数量和还款金额的情况下,我试图计算贷款的利息.我似乎无法使用基本公式得出足够接近的数字,所以我一直在尝试使用Newton Raphson方法,该方法可以在此处使用:

I'm trying to calculate the interest on a loan given the initial loan amount, the number of repayments and the amount of repayments. I can't seem to get a close enough figure using a basic formula, so I've been trying to use the Newton Raphson method, which can be seen in use here: http://www.efunda.com/formulae/finance/loan_calculator.cfm (this is the exact functionality I am looking to implement)

我尝试过使用PHPExcel中的RATE()函数,但是我的输入没有得到正确的输出,即,利率回到0.1%或类似的水平(而实际上是5.75%)

I've tried using the RATE() function from PHPExcel, however I'm not getting a correct output for my inputs, i.e. the interest rate comes back as 0.1% or similar (when in fact it's more like 5.75%)

这是PHPExcel的相关代码

This is the relevant code for PHPExcel's

/** FINANCIAL_MAX_ITERATIONS */
define('FINANCIAL_MAX_ITERATIONS', 128);

/** FINANCIAL_PRECISION */
define('FINANCIAL_PRECISION', 1.0e-08);

/**
 * Convert an array to a single scalar value by extracting the first element
 *
 * @param   mixed       $value      Array or scalar value
 * @return  mixed
 */
function flattenSingleValue($value = '') {
    while (is_array($value)) {
        $value = array_pop($value);
    }

    return $value;
}

/**
 * RATE
 *
 * Returns the interest rate per period of an annuity.
 * RATE is calculated by iteration and can have zero or more solutions.
 * If the successive results of RATE do not converge to within 0.0000001 after 20 iterations,
 * RATE returns the #NUM! error value.
 *
 * Excel Function:
 *      RATE(nper,pmt,pv[,fv[,type[,guess]]])
 *
 * @access  public
 * @category Financial Functions
 * @param   float   nper        The total number of payment periods in an annuity.
 * @param   float   pmt         The payment made each period and cannot change over the life
 *                                  of the annuity.
 *                              Typically, pmt includes principal and interest but no other
 *                                  fees or taxes.
 * @param   float   pv          The present value - the total amount that a series of future
 *                                  payments is worth now.
 * @param   float   fv          The future value, or a cash balance you want to attain after
 *                                  the last payment is made. If fv is omitted, it is assumed
 *                                  to be 0 (the future value of a loan, for example, is 0).
 * @param   integer type        A number 0 or 1 and indicates when payments are due:
 *                                      0 or omitted    At the end of the period.
 *                                      1               At the beginning of the period.
 * @param   float   guess       Your guess for what the rate will be.
 *                                  If you omit guess, it is assumed to be 10 percent.
 * @return  float
 **/
function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) {
    $nper   = (int) flattenSingleValue($nper);
    $pmt    = flattenSingleValue($pmt);
    $pv     = flattenSingleValue($pv);
    $fv     = (is_null($fv))    ? 0.0   :   flattenSingleValue($fv);
    $type   = (is_null($type))  ? 0     :   (int) flattenSingleValue($type);
    $guess  = (is_null($guess)) ? 0.1   :   flattenSingleValue($guess);

    $rate = $guess;
    if (abs($rate) < FINANCIAL_PRECISION) {
        $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv;
    } else {
        $f = exp($nper * log(1 + $rate));
        $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;
    }
    $y0 = $pv + $pmt * $nper + $fv;
    $y1 = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;

    // find root by secant method
    $i  = $x0 = 0.0;
    $x1 = $rate;
    while ((abs($y0 - $y1) > FINANCIAL_PRECISION) && ($i < FINANCIAL_MAX_ITERATIONS)) {
        $rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0);
        $x0 = $x1;
        $x1 = $rate;
        if (($nper * abs($pmt)) > ($pv - $fv))

            $x1 = abs($x1);

        if (abs($rate) < FINANCIAL_PRECISION) {
            $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv;
        } else {
            $f = exp($nper * log(1 + $rate));
            $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;
        }

        $y0 = $y1;
        $y1 = $y;
        ++$i;
    }
    return $rate;
}   //  function RATE()

我对该函数的输入是:

RATE(60, 1100, 50000);     // Outputs 0.00420298759161

RATE(60, -1100, 50000);    // Outputs 0.00959560344752

RATE(60, 1100, 66000);     // Outputs -1.05036370955

其中60是5年的月数,每月1100或-1100是还款额,50,000是总借贷额.

Where 60 is the number of months in 5 years, 1100 or -1100 is the amount repaid each month, and 50,000 is the total borrowed.

我不是数学家,上述功能对我来说意义不大,但我的阅读显示这是计算费率的最佳方法.希望我只是犯了一个愚蠢的错误...

I'm not a mathematician, the above function doesn't make much sense to me, but my reading says this is the best way to calculate the rate. Hopefully I'm just making a silly mistake...

推荐答案

您可以使用二进制搜索"代替牛顿拉夫森方法".

You can use "Binary Search" instead of "Newton Raphson method".

function rate($month, $payment, $amount)
{
    // make an initial guess
    $error = 0.0000001; $high = 1.00; $low = 0.00;
    $rate = (2.0 * ($month * $payment - $amount)) / ($amount * $month);

    while(true) {
        // check for error margin
        $calc = pow(1 + $rate, $month);
        $calc = ($rate * $calc) / ($calc - 1.0);
        $calc -= $payment / $amount;

        if ($calc > $error) {
            // guess too high, lower the guess
            $high = $rate;
            $rate = ($high + $low) / 2;
        } elseif ($calc < -$error) {
            // guess too low, higher the guess
            $low = $rate;
            $rate = ($high + $low) / 2;
        } else {
            // acceptable guess
            break;
        }
    }

    return $rate * 12;
}

var_dump(rate(60, 1000, 20000));
// Return 0.56138305664063, which means 56.1383%

二进制搜索"和牛顿拉夫森法"基本上是一种猜测方法.它会做出初步猜测,并随着时间的推移改善其猜测,直到达到可接受的猜测为止. 牛顿拉夫森法"通常比二元搜索"更快,因为它具有更好的改善猜测"策略.

The "Binary Search" and "Newton Raphson method" are basically a guess method. It make an initial guess and improve their guess over time until it meet the acceptable guess. "Newton Raphson method" usually is faster than "binary search" because it has a better "improving guess" strategy.

这个概念很简单:

我们想知道r这是利率.我们知道N,C和P.我们不知道什么是r,但让我们猜测介于0.00到1.00之间的任何数字. (在这种情况下,我们假设利率不能超过100%).

We want to know r which is the interest rate. We know, N, C, and P. We don't know what is r, but let just guess any number between 0.00 to 1.00. (In this case, we assume that the interest rate cannot be over 100%).

  • 第1步:随机猜测
  • 第2步:将费率插入公式,
  • 第3步:检查猜测值是否太低,更高的猜测值,转到第2步
  • 步骤4:检查猜测是否过高,降低猜测,转到步骤2
  • 第5步:我们得到了可以接受的费率.
  • 步骤6:r是月费率.乘以12即可得出年利率.
  • Step 1: Make a random guess
  • Step 2: Plug the rate into formula,
  • Step 3: Check if the guess is too low, higher the guess, goto Step 2
  • Step 4: Check if the guess is too high, lower the guess, goto Step 2
  • Step 5: We got acceptable rate.
  • Step 6: r is monthly rate. Multiple by 12 to get annually rate.

这篇关于用PHP计算利率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆