Twitter Subscribe to PHP Blog RSS Feed Email RSS

递归函数 – 还贷计算器

添加评论 2010年6月2日
可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明

递归函数(recursive function),即调用自身的函数,通常有很好的实用价值,用来将复杂的问题分解为简单的情况,反复调用自身处理直到问题解决。

这里以还贷计算器中的等额本息(每月以相等金额还贷款的本金加利息)还款为例子,输出一个表格,例举出每一期还款所需要的偿还的金额,所还的利息以及每月的贷款本金减少额。

先做一个HTML表接受用户输入,代码如下:

[code=”xml”]

等额本息还款

贷款年限:

年利率(%):


[/code]

现在编写实现主要功能的递归函数。需要了解到的是,每月本金减少额=每月还款额-每月的利息。当贷款本金不等于0时,重复执行函数到贷款本金为0时结束。

注:《PHP与MySQL 5程序设计》(第2版)上有这个例子,但书上 if 判断当本金为 0 时执行 exit,将导致不能输出 </table> 结束标志和后面的 HTML代码,此处做了修改,本金为 0 时直接输出</table>。

[code=”php”]

//Recursive Function(递归函数)

/*
$paymentNum–还款期数
$balance–贷款本金
$periodicPayment–每月还款额
$paymentInterest–每月的利息
$paymentPrincipal–每月本金减少额
$monthlyInterest–月利率
*/

function amortizationTable($paymentNum,$periodicPayment,$balance,$monthlyInterest) {
$paymentInterest = round($balance * $monthlyInterest,2);
$paymentPrincipal = round($periodicPayment – $paymentInterest,2);
$newBalance = round($balance – $paymentPrincipal,2);
echo “

$paymentNum \$”.number_format($balance,2).” \$”.number_format($periodicPayment,2).” \$”.number_format($paymentInterest,2).” \$”.number_format($paymentPrincipal,2).”

“;
//If balance not yet zero,recursively call amortizationTable()
if ($newBalance > 0) {
$paymentNum++;
amortizationTable($paymentNum,$periodicPayment,$newBalance,$monthlyInterest);
}
else {
echo “

“;
}
} //end amortizationTable()

[/code]

接下来计算每月还款额以及执行递归函数。

Tips:每月还款额=贷款本金×月利率×(1+月利率)^还款总期数/((1+月利率)^还款总期数-1 )

x^y 表示x的y次方

因为将表单和函数执行写在一个文件上,因此再添加一个 if 判断,有表单数据递交时才执行后面的代码

[code=”php”]

if (isset($_POST[‘submit’]))
{

# Loan balance (贷款余额)
$balance = $_POST[‘balance’];

# Loan interest(利、息) rate
$interestRate = $_POST[‘rate’] / 100;

# Mothly interest rate
$monthlyInterest = $interestRate / 12;

# Term length of the loan(固定贷款期限),in year.
$termLength = $_POST[‘term’];

# Number of payments per year.
$paymentsPerYear = 12;

# Payment iteration(迭代)
$paymentNumber = 1;

# Perform preliminary calculations
$totalPayments = $termLength * $paymentsPerYear;
$intCalc = 1 + $interestRate / $paymentsPerYear;    # 1+月利率
$periodicPayment = $balance * pow($intCalc,$totalPayments) * ($intCalc -1 ) / (pow($intCalc,$totalPayments) – 1);
$periodicPayment = round($periodicPayment,2);
echo “

您计算的每月还款额为: ¥”.$periodicPayment.”

“;
?>

[/code]

使用递归策略通常能大幅减少代码量,提高重用性。虽然递归并不总是最好的解决办法,但是可以作为一个有益的补充。

PS:关于 HTML 表格的一些问题

<thead>, <tbody> 和 <tfoot>很少被用到,这是由于浏览器对它们的支持不太好。但是用这些标签定义表格可以在使用被支持的浏览器(如 Firefox)打印时产生一个效果,就是当表格过长超过一个打印页时将每页添加表格页眉和页脚,以方便查看数据。感兴趣的可以运行代码试试。

经过我的测试Windows 7下firefox和ie8,在只使用 <thead> 和 <tbody> 而不使用 <tfoot> 时打印页眉页脚正常。在 Mac 下仅 firefox 正常。至于为什么添加了 <tfoot> 反而出现问题我也不甚理解,请知晓的朋友在此留言。

评论

  1. 老飞

    欢迎到我的博客讨论编程技术
    http://fly.altech-it.cn/


Payment Number Balance Payment Interest Principal
Now We are Finished!