我正在努力用PHP转换抵押贷款计算器,但我不一定需要PHP解决方案。我正在寻找复制Excel RATE
函数所需的逻辑。我找到了一个使用二分法的解决方案,如果情况变得更糟,我就会使用它。
我知道在interwebs世界中有人知道这样的功能,所以我很乐意有一个简单的答案,而不是从头开始创建一个解决方案。
参考文献:
由于
答案 0 :(得分:8)
使用从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()
答案 1 :(得分:0)
我尝试使用上面的代码,但结果与Excel(或Google电子表格)不同。
我不知道你是否需要实现这个功能,但无论如何,我看看这个算法是如何构建的,即使我无法访问excel源代码(或谷歌工作表),我发现这不是一个简单的计算。关于这个数学,更多内容可以在这里阅读:
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;
}
答案 2 :(得分:0)
对于Laravel,请使用相同的功能,但要删除定义
define('FINANCIAL_MAX_ITERATIONS', 128);
define('FINANCIAL_PRECISION', 1.0e-08);
和financial_max_iterations = 20; ->相同的Excel
代码是:
function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) {
$financial_max_iterations = 20;
$financial_precision = 0.00000008;
$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;
}
对我有用
答案 3 :(得分:0)
TL; DR::这是SQL Server版本。它不适用于某些值,并且上面的PHP代码对于相同的值可能会失败。
长答案::我需要SQL Server的RATE函数。使用上面的PHPExcel答案,并使用https://charlottecredittechnology.blogspot.com/2013/05/sql-2008-excel-like-rate-function-part.html,我编写了一个SQL Server标量函数:
ALTER function [dbo].[Rate](
@nper integer, @pmt float, @pv float, @fv float, @type bit = 0, @guess float = 0.1
) returns numeric(38,10) as
/*
Calculate the effective interest rate of a sequence of regular payments.
*/
begin
declare @returns numeric(38,10) = 0;
if @type is null set @type = 0;
declare @i integer;
declare @rate float = @guess;
declare @FINANCIAL_MAX_ITERATIONS integer = 100;
declare @FINANCIAL_PRECISION float = 0.0000001;
declare @y float, @y0 float, @y1 float, @f float, @x0 float, @x1 float;
set @rate = @guess;
if Abs(@rate) < @FINANCIAL_PRECISION
begin
set @f = 0;
set @y = @pv * (1+@nper*@rate) + @pmt * (1+@rate*@type) * @nper + @fv;
end
else
begin
set @f = Exp(@nper * Log(1+@rate));
set @y = @pv * @f + @pmt * (1/@rate + @type) * (@f-1) + @fv;
end;
set @y0 = @pv + @pmt * @nper + @fv;
set @y1 = @pv * @f + @pmt * (1/@rate + @type) * (@f-1) + @fv;
-- Newton secant method.
set @i = 0;
set @x0 = 0;
set @x1 = @rate;
while Abs(@y0-@y1) > @FINANCIAL_PRECISION and @i < @FINANCIAL_MAX_ITERATIONS
begin
set @rate = (@y1 * @x0 - @y0 * @x1) / (@y1-@y0);
set @x0 = @x1;
set @x1 = @rate;
if Abs(@rate) < @FINANCIAL_PRECISION
begin
set @y = @pv * (1+@nper*@rate) + @pmt * (1+@rate*@type) * @nper + @fv;
end
else
begin
set @f = Exp(@nper * Log(1+@rate));
set @y = @pv * @f + @pmt * (1/@rate + @type) * (@f-1) + @fv;
end;
set @y0 = @y1;
set @y1 = @y;
set @i = @i + 1;
end;
return Convert(numeric(38,10), @rate);
end;
不幸的是,它并不总是有效。这是我汇总并使用Excel检查的一些测试的结果:
-- (1) OK
select dbo.RATE(4*12, -200, 8000, 0, default, default) * 12 -- SQL formula
0.0924 (9.24%) -- SQL result
=RATE(4*12, -200, 8000, 0) * 12 -- Excel formula
9.24% -- Excel result
-- (2) OK
select dbo.RATE(12, -1000, 12000, 0, default, default) * 12 -- SQL formula
0 (0%) -- SQL result
=RATE(12, -1000, 12000, 0) * 12 -- Excel formula
0% -- Excel result
-- (3) OK
select dbo.RATE(30, -400, 4000, 0, 1, default) -- SQL formula
0.10496 (10.496%) -- SQL result
=RATE(30, -400, 4000, 0, 1) -- Excel formula
10.4964% -- Excel result
-- (4) OK
select dbo.RATE(120, 28.1, -2400, 0, default, default) -- SQL formula
0.0059905810 (0.599%) -- SQL result
=RATE(120, 28.1, -2400, 0) -- Excel formula
0.5991% -- Excel result
-- (5) OK
select dbo.RATE(10, -1000, 10000, -10000, default, default) -- SQL formula
0.1 (10%) -- SQL result
=RATE(10, -1000, 10000, -10000) -- Excel formula
10% -- Excel result
-- (6) WRONG ANSWER (unless you set @guess to 0.01)
select dbo.RATE(475, -1022.93, 272779.21, 0, default, default) -- SQL formula
0 -- SQL result
=RATE(475, -1022.93, 272779.21, 0, 0) -- Excel formula
0.2716% -- Excel result
-- (7) ERROR
select dbo.RATE(252, -29002.85, 2500000, 0, default, default) -- SQL formula
invalid floating point operation -- SQL result
=RATE(252, -29002.85, 2500000, 0) -- Excel formula
1.0833% -- Excel result
-- (8) OK
select dbo.RATE(24, -46.14, 1000, 0, default, default) -- SQL formula
0.0083244385 (0.83244%) -- SQL result
=RATE(24, -46.14, 1000, 0) -- Excel formula
0.8324% -- Excel result
测试(7)和(8)来自RATE Function from EXCEL in Swift providing different results,并使用Newton-Raphson方法寻找答案。