Quantcast
Channel: PHP Stone
Viewing all articles
Browse latest Browse all 30

递归函数 –还贷计算器

$
0
0

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

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

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



<h2>等额本息还款</h2>
<form action="<?php $PHP_SELF; ?>" method="post">
<p>
贷款本金:<br />
<input type="text" id="balance" name="balance" size="20" maxlength="40" />
</p>
<p>
贷款年限:<br />
<input type="text" id="term" name="term" size="20" maxlength="40" />
</p>
<p>
年利率(%):<br />
<input type="text" id="rate" name="rate" size="20" maxlength="40" />
</p>
<input type="submit" id="submit" name="submit" value="计算" />
</form>


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

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



//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 "<tr>
<td>$paymentNum</td>
<td>\$".number_format($balance,2)."</td>
<td>\$".number_format($periodicPayment,2)."</td>
<td>\$".number_format($paymentInterest,2)."</td>
<td>\$".number_format($paymentPrincipal,2)."</td>
</tr>";
//If balance not yet zero,recursively call amortizationTable()
if ($newBalance > 0) {
$paymentNum++;
amortizationTable($paymentNum,$periodicPayment,$newBalance,$monthlyInterest);
}
else {
echo "</table>";
}
} //end amortizationTable()


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

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

x^y 表示x的y次方

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



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 "<p>您计算的每月还款额为: ¥".$periodicPayment."</p>";
?>
<table width='50%' align='center' border='1'>
<thead>
<tr>
<th>Payment Number</th><th>Balance</th>
<th>Payment</th><th>Interest</th><th>Principal</th>
</tr>
</thead>

<tfoot>
<tr>
<th colspan="5">Now We are Finished!</th>
</tr>
</tfoot>
<?php
# Call recursive function
amortizationTable($paymentNumber,$periodicPayment,$balance,$monthlyInterest);
} //End if
?>


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

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

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

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


Viewing all articles
Browse latest Browse all 30

Trending Articles