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()));
}
}
}
}