等额本息计算式的推导
其中P是全额, R是月息, N是期数.
对于等额本息, 每个月的还款数额相同, 但是利息是递减的, 第一个月是全额的一个月利息, 第二个月是去掉第一个月本金后剩余金额的一个月利息, 如下:
假定每月还款为x, 总借款金额为m, 月息为r, 各月所还本金可以按如下计算
a1 = x - m*r
a2 = x - (m - a1)*r
a3 = x - (m - a1 - a2)*r
...
an = x - (m - a1 - ... - an-1)*r
an+1 = x (因为a1 + ... + an=m)
将a1代入a2的表达式, 然后将a1和a2再代入入a3的表达式, 会得到
a3 = (x - mr)*(1+r)2
a4 = (x - mr)*(1+r)3
...
an+1 = (x - mr)*(1+r)n = x
这就得出了等额本息的x的计算公式.
以天计息的等额本息推导
如果计息需要精确到天, 假设总本金为P, 日利率为r, 一共有n期, 每一期还款为x, 其到期后的本金余额为 Pn 如下:
P1 = P - (x - P * d1 * r) = P * (1 + d1 * r) - x
P2 = P1 * (1 + d2 * r) - x
P3 = P2 * (1 + d3 * r) - x
...
Pn-1 = Pn-2 * (1 + dn-1 * r) - x
Pn = Pn-1 * (1 + dn * r) - x = 0
代入则可以得到
(((P * (1 + d1 * r) - x) * (1 + d2 * r) - x) * (1 + d3 * r) - x) ... * (1 + dn * r) = x
通过不断代入dn即可求得x值
Java实现
/** * 按日标准等额本息法计算每月还款额 * * @param principal 本金金额 * @param rate 年化利率 * @param dueDates 日期序列 * @return 与日期序列大小一致, 因为还款序列正好比日期序列少一位, 使用最后一个值存储月均还款额, 其他则为每次的本金还款额 */ public static BigDecimal[] calEquatedMonthlyInstallment(BigDecimal principal, BigDecimal rate, List<Date> dueDates) { BigDecimal[] output = new BigDecimal[dueDates.size()]; BigDecimal k = BigDecimal.ZERO , tmp = BigDecimal.ONE; for (int i = dueDates.size() - 1; i > 0; i--) { int period = TimeUtil.getDaysDiff(dueDates.get(i - 1), dueDates.get(i)); k = BigDecimal.valueOf(period).divide(BigDecimal.valueOf(365), 8, BigDecimal.ROUND_HALF_UP).multiply(rate).add(BigDecimal.ONE); output[i - 1] = k; // 记住每一步的本金换算比例, 用于倒推本金 tmp = tmp.divide(k, 8, BigDecimal.ROUND_HALF_UP).add(BigDecimal.ONE); } // 边界: 最后一步的tmp值并无1, 要扣除后再计算 BigDecimal amount = principal.divide(tmp.subtract(BigDecimal.ONE), 2, BigDecimal.ROUND_HALF_UP); output[dueDates.size() - 1] = amount; //月还款额 BigDecimal p, pnext = BigDecimal.ZERO, total = BigDecimal.ZERO; // total:累计本金的临时变量, pnext后一个月的本金初始为0, p此月的本金. for (int i = dueDates.size() - 2; i > 0; i--) { p = pnext.add(amount).divide(output[i], 2, BigDecimal.ROUND_HALF_UP); output[i] = p.subtract(pnext); // 差就是本月的本金还款额 total = total.add(output[i]); pnext = p; } output[0] = principal.subtract(total); // 第一个月用差额, 以满足和与本金精确相等 return output; }