根据贷款还款方式(等额本金,等额本息,等本等息,先息后本),计算本息

package com.alex.examples.utils.money;

import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;

@Data
public class MoneyVo implements Serializable {
    private Integer number;//期数
    private BigDecimal monthPrincipalInterest;//本息
    private BigDecimal monthPrincipal;//本金
    private BigDecimal monthInterest;//利息

}
package com.alex.examples.utils.money;

import cn.hutool.core.math.MathUtil;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class MoneyUtils {
    public static void main(String[] args) {
        Long principal = 1000000L; //贷款本息
        Double interest = 0.01; //月利息
        Integer months = 12; //贷款期数

//        //等额本金
//        List<MoneyVo> list = DEBJ(new BigDecimal(MathUtil.centToYuan(principal)), interest, months);
//        list.forEach(vo -> System.out.println("期数:" + vo.getNumber()
//                + ",月供(元):" + vo.getMonthPrincipalInterest()
//                + ",本金(元):" + vo.getMonthPrincipal()
//                + ",利息(元):" + vo.getMonthInterest()));

//        //等本等息
//        List<MoneyVo> list = DBDX(new BigDecimal(MathUtil.centToYuan(principal)), interest, months);
//        list.forEach(vo -> System.out.println("期数:" + vo.getNumber()
//                + ",月供(元):" + vo.getMonthPrincipalInterest()
//                + ",本金(元):" + vo.getMonthPrincipal()
//                + ",利息(元):" + vo.getMonthInterest()));

        //先息后本
        List<MoneyVo> list = XXHB(new BigDecimal(MathUtil.centToYuan(principal)), interest, months);
        list.forEach(vo -> System.out.println("期数:" + vo.getNumber()
                + ",月供(元):" + vo.getMonthPrincipalInterest()
                + ",本金(元):" + vo.getMonthPrincipal()
                + ",利息(元):" + vo.getMonthInterest()));
    }

    /**
     * 等额本金
     * 定义:月还款总额逐月降低;月还款本金固定,为贷款总金额/期数;月还款利息逐渐降低,为每月剩余贷款余额*单期利息
     * 规则:例如【本金10000,月息1%,贷款12期】,则月还款本金=本金/期数;月利息:每期剩余本金*利息,
     * 如第一期应还利息=10000*1%=100;第二期应还利息=(10000-833.33)*1%=91.67......
     *
     * @param principal:本金,单位分
     * @param interest:月利息,单位分
     * @param months:贷款期数,单位月
     * @return
     */
    public static List<MoneyVo> DEBJ(BigDecimal principal, Double interest, Integer months) {
        List<MoneyVo> list = new ArrayList<>();
        BigDecimal money = principal; //剩余本金
        BigDecimal monthPrincipal = principal.divide(new BigDecimal(months), 2, BigDecimal.ROUND_HALF_UP); //月还款本金

        for (int i = 1; i < months + 1; i++) {
            MoneyVo vo = new MoneyVo();
            vo.setNumber(i);
            vo.setMonthPrincipal(monthPrincipal);

            //月应还利息
            if (i == 1) {
                BigDecimal monthInterest = principal.multiply(new BigDecimal(interest).setScale(2, BigDecimal.ROUND_HALF_UP));
                vo.setMonthInterest(monthInterest);

                money = principal.subtract(monthPrincipal).setScale(2, BigDecimal.ROUND_HALF_UP);
            } else {
                BigDecimal monthInterest = money
                        .multiply(new BigDecimal(interest).setScale(2, BigDecimal.ROUND_HALF_UP))
                        .setScale(2, BigDecimal.ROUND_HALF_UP);
                vo.setMonthInterest(monthInterest);

                money = money.subtract(monthPrincipal).setScale(2, BigDecimal.ROUND_HALF_UP);
            }

            //月应还本息
            BigDecimal monthPrincipalInterest = vo.getMonthPrincipal().add(vo.getMonthInterest()).setScale(2, BigDecimal.ROUND_HALF_UP);
            vo.setMonthPrincipalInterest(monthPrincipalInterest);

            //整合数据
            list.add(vo);
        }
        return list;
    }

    /**
     * 等本等息
     * 定义:月还款总额不变;月还款本金不变,为贷款总金额/期数;月还款利息不变,为贷款总金额*单期利率
     *
     * @param principal:本金,单位分
     * @param interest:月利息,单位分
     * @param months:贷款期数,单位月
     * @return
     */
    public static List<MoneyVo> DBDX(BigDecimal principal, Double interest, Integer months) {
        List<MoneyVo> list = new ArrayList<>();
        //月还款本金
        BigDecimal monthPrincipal = principal.divide(new BigDecimal(months), 2, BigDecimal.ROUND_HALF_UP);
        //月还款利息
        BigDecimal monthInterest = principal.multiply(new BigDecimal(interest)).setScale(2, BigDecimal.ROUND_HALF_UP);
        //月还款本息
        BigDecimal monthPrincipalInterest = monthPrincipal.add(monthInterest).setScale(2, BigDecimal.ROUND_HALF_UP);
        for (int i = 1; i < months + 1; i++) {
            MoneyVo vo = new MoneyVo();
            vo.setNumber(i);
            vo.setMonthPrincipal(monthPrincipal);
            vo.setMonthInterest(monthInterest);
            vo.setMonthPrincipalInterest(monthPrincipalInterest);
            list.add(vo);
        }
        return list;
    }

    /**
     * 先息后本
     * 定义:月还款总额不变,为月还款利息;月还款本金为0,在最后一期还总贷款额本金;月还款利息不变,为贷款总金额*单期利息
     *
     * @param principal:本金,单位分
     * @param interest:月利息,单位分
     * @param months:贷款期数,单位月
     * @return
     */
    public static List<MoneyVo> XXHB(BigDecimal principal, Double interest, Integer months) {
        List<MoneyVo> list = new ArrayList<>();
        //月还款本息=月还款利息
        BigDecimal monthPrincipalInterest = principal.multiply(new BigDecimal(interest)).setScale(2, BigDecimal.ROUND_HALF_UP);
        for (int i = 1; i < months + 1; i++) {
            MoneyVo vo = new MoneyVo();
            vo.setNumber(i);
            vo.setMonthInterest(monthPrincipalInterest);
            vo.setMonthPrincipalInterest(monthPrincipalInterest);
            if (i < months) {
                vo.setMonthPrincipal(new BigDecimal(0));
            } else {
                vo.setMonthPrincipal(principal);
            }
            list.add(vo);
        }
        return list;
    }
}
package com.alex.examples.utils.money;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 等额本息计算工具类
 *
 * <p>
 * 等额本息还款,也称定期付息,即借款人每月按相等的金额偿还贷款本息,其中每月贷款利息按月初剩余贷款本金计算并逐月结清。把按揭贷款的本金总额与利息总额相加,
 * 然后平均分摊到还款期限的每个月中。作为还款人,每个月还给银行固定金额,但每月还款额中的本金比重逐月递增、利息比重逐月递减。
 * <p>
 * 年利率=月利率×12(月)=日利率×360(天)
 * <p>
 * 月利率=年利率÷12(月)=日利率×30(天)
 * <p>
 * 日利率=年利率÷360(天)=月利率÷30(天)。
 */
public class AverageCapitalPlusInterestUtils {

    /**
     * 每月偿还本金和利息
     * <p>
     * 公式:每月偿还本息=〔贷款本金×月利率×(1+月利率)^还款月数〕÷〔(1+月利率)^还款月数-1〕
     *
     * @param invest     总借款额(贷款本金,单位分)
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 每月偿还本金和利息(入1 单位分)
     */
    public static double getPerMonthPrincipalInterest(double invest, double yearRate, int totalMonth) {
        double monthRate = yearRate / 12;
        double perMonthPrincipalInterest = invest * (monthRate * Math.pow(1 + monthRate, totalMonth)) / (Math.pow(1 + monthRate, totalMonth) - 1);
        return new BigDecimal(perMonthPrincipalInterest).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 等额本息的每月偿还利息
     * <p>
     * 公式:每月偿还利息=贷款本金×月利率×〔(1+月利率)^还款月数-(1+月利率)^(还款月序号-1)〕÷〔(1+月利率)^还款月数-1〕
     *
     * @param invest     总借款额(贷款本金,分)
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 每月偿还利息(入1 单位分)
     */
    public static Map<Integer, Double> getPerMonthInterest(double invest, double yearRate, int totalMonth) {
        Map<Integer, Double> map = new HashMap<>();
        double monthRate = yearRate / 12;
        double monthInterest;
        for (int i = 1; i < totalMonth + 1; i++) {
            double multiply = invest * monthRate;
            double sub = Math.pow(1 + monthRate, totalMonth) - Math.pow(1 + monthRate, i - 1);
            monthInterest = multiply * sub / (Math.pow(1 + monthRate, totalMonth) - 1);
            map.put(i, new BigDecimal(monthInterest).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        }
        return map;
    }

    /**
     * 等额本息的每月偿还本金(月还本息-月还利息)
     *
     * @param invest     总借款额(贷款本金,分)
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 每月偿还本金(取整舍 单位分)
     */
    public static Map<Integer, Double> getPerMonthPrincipal(double invest, double yearRate, int totalMonth) {
        double monthRate = yearRate / 12;
        double monthIncome = invest * monthRate * Math.pow(1 + monthRate, totalMonth)
                / (Math.pow(1 + monthRate, totalMonth) - 1);
        double perMonthPrincipalInterest = new BigDecimal(monthIncome).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

        Map<Integer, Double> mapPrincipal = new HashMap<>();
        double monthInterest;
        for (int i = 1; i < totalMonth + 1; i++) {
            Double multiply = invest * monthRate;
            double sub = (Math.pow(1 + monthRate, totalMonth)) - (Math.pow(1 + monthRate, i - 1));
            monthInterest = multiply * sub / (Math.pow(1 + monthRate, totalMonth) - 1);
            double monthInterestL = new BigDecimal(monthInterest).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            mapPrincipal.put(i, new BigDecimal(perMonthPrincipalInterest).subtract(new BigDecimal(monthInterestL)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        }
        return mapPrincipal;
    }

    /**
     * 等额本息的总利息
     *
     * @param invest     总借款额(贷款本金)
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 总利息 (单位分)
     */
    public static double getInterestCount(double invest, double yearRate, int totalMonth) {
        double count = 0;
        Map<Integer, Double> mapInterest = getPerMonthInterest(invest, yearRate, totalMonth);

        for (Map.Entry<Integer, Double> entry : mapInterest.entrySet()) {
            count = new BigDecimal(count).add(new BigDecimal(entry.getValue())).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        return count;
    }


    public static void main(String[] args) {
        double invest = 10000; // 本金
        int month = 12;
        double yearRate = 0.01; // 年利率

        Double perMonthPrincipalInterest = getPerMonthPrincipalInterest(invest, yearRate, month);
        System.out.println("等额本息---每月还款本息(每月还款本金+每月还款利息):" + perMonthPrincipalInterest);

        Map<Integer, Double> mapPrincipal = getPerMonthPrincipal(invest, yearRate, month);
        System.out.println("等额本息---每月还款本金:" + mapPrincipal);

        Map<Integer, Double> mapInterest = getPerMonthInterest(invest, yearRate, month);
        System.out.println("等额本息---每月还款利息:" + mapInterest);

        Double count = getInterestCount(invest, yearRate, month);
        System.out.println("等额本息---总利息:" + count);

        for (int i = 1; i < month + 1; i++) {
            if (i < month) {
                System.out.println("等额本息---" + i + "月还款本金:" + mapPrincipal.get(i) + ",还款利息:" + mapInterest.get(i));

                //剩余本金:总的本金-每月还款本金
                invest = new BigDecimal(invest).subtract(new BigDecimal(mapPrincipal.get(i))).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            } else {
                //最后一个月的还款利息=每月还款本息-剩余本金
                System.out.println("等额本息---" + i + "月还款本金:" + invest + ",还款利息:" + (new BigDecimal(perMonthPrincipalInterest).subtract(new BigDecimal(invest)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()));
            }
        }
    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值