PHP版Excel RATE函数适配逐年递增还款额(pmt)的实现问询
支持递增还款额的PHP版RATE函数实现
原函数仅支持固定还款额的年金利率计算,我们可以通过新增年增长率参数,并替换核心的现值计算公式为增长型年金现值公式,来实现逐年递增还款额的利率计算需求。
修改后的完整代码
function RATE($nper, $pmt, $growth = 0.0, $pv, $fv = 0.0, $type = 0, $guess = 0.1) { $financial_max_iterations = 20; $financial_precision = 0.00000008; $rate = $guess; // 计算当前利率下的现金流现值总和(PV + 递增还款现值 + 终值现值) $y = calculatePresentValue($nper, $pmt, $growth, $pv, $fv, $type, $rate); $y0 = calculatePresentValue($nper, $pmt, $growth, $pv, $fv, $type, 0.0); $y1 = $y; // 割线法迭代求解利率 $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; $y = calculatePresentValue($nper, $pmt, $growth, $pv, $fv, $type, $rate); $y0 = $y1; $y1 = $y; ++$i; } return $rate; } /** * 计算增长型年金的现值总和 */ function calculatePresentValue($nper, $pmt, $growth, $pv, $fv, $type, $rate) { $rateAbs = abs($rate); $growthAbs = abs($growth); // 计算还款额的现值部分 if ($rateAbs < 0.0000001) { // 利率接近0时的简化计算 if ($growthAbs < 0.0000001) { // 无增长,固定还款额 $pmtPresentValue = $pmt * (1 + $rate * $type) * $nper; } else { // 利率为0,有增长:求和pmt*(1+g)^t,t从0到nper-1 $pmtPresentValue = $pmt * ((pow(1 + $growth, $nper) - 1) / $growth) * (1 + $rate * $type); } } else { if (abs($rate - $growth) < 0.0000001) { // 利率等于增长率时的简化计算 $pmtPresentValue = $pmt * (1 + $rate * $type) * $nper * pow(1 + $rate, -$type); } else { // 通用增长型年金现值公式 $growthFactor = (1 + $growth) / (1 + $rate); $pmtPresentValue = $pmt * (1 + $rate * $type) * (1 - pow($growthFactor, $nper)) / ($rate - $growth); } } // 计算终值的现值 $fvPresentValue = $fv / pow(1 + $rate, $nper); // 总现值总和 = 初始现值 + 还款现值 + 终值现值 return $pv + $pmtPresentValue + $fvPresentValue; }
关键修改说明
- 新增参数:加入
$growth参数,代表还款额的年增长率(传入小数形式,如10%则传0.1),默认值为0,兼容原函数的固定还款额场景。 - 拆分计算逻辑:将现值计算抽离为
calculatePresentValue函数,便于维护,同时完整实现了增长型年金的现值计算:- 区分利率为0、利率等于增长率、通用情况三种场景,避免除零错误并保证计算精度
- 保留原函数的
type参数(期初/期末还款)逻辑
- 保留迭代逻辑:原有的割线法迭代求解逻辑不变,确保利率计算的收敛性和精度。
调用示例
以你提到的场景为例:贷款本金80000元,首年还款1200元,年增幅10%,期限20年,期末还款,计算利率:
// 参数说明:期数nper=20,首年还款pmt=-1200(支出为负),增长率growth=0.1,现值pv=80000(收入为正) $rate = RATE(20, -1200, 0.1, 80000); echo "年利率:" . round($rate * 100, 2) . "%";
注意事项
- 现金流符号规则遵循Excel标准:流入为正,流出为负(如贷款本金是流入,还款是流出)
- 增长率需传入小数(如5%传0.05),若为负则代表还款额逐年递减
- 若迭代20次仍未收敛,可适当调整
$financial_max_iterations参数增加迭代次数
内容的提问来源于stack exchange,提问作者T.K
相关产品推荐
相关产品推荐

