• 等额本息计算式的推导


    其中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;
        }
  • 相关阅读:
    常见正则总结
    word 操作教程
    word调整技巧
    关于如何自定义handler
    html 处理
    iis 导入和导出配置——iis管理
    前端学习
    动态添加js的方法
    jquery学习笔记
    php学习笔记
  • 原文地址:https://www.cnblogs.com/milton/p/4868301.html
Copyright © 2020-2023  润新知