使用牛顿方法重新创buildExcel RATE函数

我正在使用PHP转换抵押计算器,但我不一定需要PHP解决scheme。 我正在寻找复制Excel RATE函数所需的逻辑。 我find了一个使用二分法的解决scheme,如果情况变得更糟,我使用它。

我知道interwebs世界里有人有这样的function的知识,所以我很乐意有一个简单的答案,而不是从头开始创build一个解决scheme。

参考文献:

  • http://office.microsoft.com/en-us/excel-help/rate-HP005209232.aspx
  • http://en.wikipedia.org/wiki/Newton%27s_method

谢谢

使用来自PHPExcel的割线方法(牛顿法的有限差分近似)实现MS Excel RATE()函数:

 define('FINANCIAL_MAX_ITERATIONS', 128); define('FINANCIAL_PRECISION', 1.0e-08); function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) { $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 (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() 

我试图使用上面的代码,但结果与Excel(或Google Spreadsheet)不一样。

我不知道你是否需要实现这个function,但无论如何,我看着如何构build这个algorithm,即使我无法访问Excel的源代码(或谷歌工作表),我发现这不是一个简单的计算。 关于这个math,更多可以在这里阅读:

https://brownmath.com/bsci/loan.htm#Eq8

PHP中的函数可能是这样的:

 function rate($nprest, $vlrparc, $vp, $guess = 0.25) { $maxit = 100; $precision = 14; $guess = round($guess,$precision); for ($i=0 ; $i<$maxit ; $i++) { $divdnd = $vlrparc - ( $vlrparc * (pow(1 + $guess , -$nprest)) ) - ($vp * $guess); $divisor = $nprest * $vlrparc * pow(1 + $guess , (-$nprest - 1)) - $vp; $newguess = $guess - ( $divdnd / $divisor ); $newguess = round($newguess, $precision); if ($newguess == $guess) { return $newguess; } else { $guess = $newguess; } } return null; }