/** * 阿里借呗计息还款规则说明实现 * * 测试阿里案例和韩哥案例通过 * @return */ package jdongtech.jiebaiUtils; import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; import java.util.Map; import jdongtech.interestUtils.AverageCapitalPlusInterestUtils; public class advanceRepayMore { public static void main(String[] args) { Calendar lendDay = Calendar.getInstance(); // 借款日期 Calendar rebackDay = Calendar.getInstance();// 还款日期 double rebackInvest = 0; // 还款金额 double invest = 0; // 借款本金 int month = 0; // 期数 double yearRate = 0; // 年利率 int acctOffsetDay = 15; // 平移日期 int accountDay = 25; // 账单日,蚂蚁会把账单日设置成借款当日 // 文件示例 lendDay.set(Calendar.MONTH, 9); lendDay.set(Calendar.DAY_OF_MONTH, 13); rebackInvest = 100.24; // rebackInvest = 60.04; rebackDay.set(Calendar.MONTH, 9); rebackDay.set(Calendar.DAY_OF_MONTH, 14); invest = 1200; // 本金 month = 12; // 期数 yearRate = 7.2 / 100; // 年利率 acctOffsetDay = 15; accountDay = 25; // 韩哥示例 lendDay.set(Calendar.MONTH, 4); lendDay.set(Calendar.DAY_OF_MONTH, 13); rebackInvest = 60.04; rebackDay.set(Calendar.MONTH, 4); rebackDay.set(Calendar.DAY_OF_MONTH, 13); invest = 120; // 本金 month = 6; // 期数 yearRate = 14.4 / 100; // 年利率 acctOffsetDay = 15; accountDay = 13; // 账单日,蚂蚁会把账单日设置成借款当日 double dateRate = yearRate / 360; int[] daysCount = new int[month]; int IncreaseFlag = 0; Calendar lendCalOffset = (Calendar) lendDay.clone(); lendCalOffset.add(Calendar.DATE, acctOffsetDay); Calendar accCal = (Calendar) lendDay.clone(); accCal.set(Calendar.DAY_OF_MONTH, accountDay); Calendar accCalBegin = (Calendar) accCal.clone(); if (lendCalOffset.before(accCal)) { } else { accCalBegin.add(Calendar.MONTH, 1); IncreaseFlag = 1; } Calendar accCalEnd = (Calendar) accCal.clone(); accCalEnd.add(Calendar.MONTH, month - 1); System.out.println(lendDay.getTime() + "借款日期"); System.out.println(accCalBegin.getTime() + "开始"); System.out.println(accCalEnd.getTime() + "结束"); int daysLending = RepayUtils.daysOffset(lendDay, accCalEnd); System.out.println("借款经历" + daysLending + "天"); Calendar accCalPerEnd = (Calendar) accCalBegin.clone(); for (int i = 0; i < month; i++) { Calendar accCalPerBeg; if (i == 0) { accCalPerBeg = (Calendar) lendDay.clone(); } else { accCalPerBeg = (Calendar) accCalPerEnd.clone(); accCalPerBeg.add(Calendar.MONTH, -1); } int daysPer = RepayUtils.daysOffset(accCalPerBeg, accCalPerEnd); daysCount[i] = daysPer; accCalPerEnd.add(Calendar.MONTH, 1); } System.out.println("部分还款前计划:"); normalRepay.getPerMonthPrincipalInterestBig(invest, dateRate, month, daysCount, IncreaseFlag); System.out.println("提前还款日期:" + rebackDay.getTime()); int curPeriod = 0; int daysCurPeriod = RepayUtils.daysOffset(lendDay, rebackDay); for (int i = 0; i < daysCount.length; i++) { daysCurPeriod = daysCurPeriod - daysCount[i]; if (daysCurPeriod <= 0) { // 账单日算当前期 curPeriod = i; daysCurPeriod = daysCurPeriod + daysCount[i]; i = daysCount.length; } } System.out.println("提前还款当期期数:" + curPeriod); System.out.println("提前还款当期天数:" + daysCurPeriod); System.out.println("部分还款后计划:"); getPerMonthPrincipalInterestBigRebackSome(invest, dateRate, month, daysCount, IncreaseFlag, rebackInvest, curPeriod, daysCurPeriod); } /** * 计算实际等额本息每月额度 * * @return */ public static double getPerMonthPrincipalInterestBigRebackSome(double invest, double dateRate, int totalmonth, int[] daysCount, int IncreaseFlag, double rebackInvest, int curPeriod, int daysCurPeriod) { IncreaseFlag = 1; if (daysCurPeriod == 0) { daysCurPeriod = 1; } double perMonthStandard = AverageCapitalPlusInterestUtils.getPerMonthPrincipalInterest(invest, dateRate * 360, totalmonth); double perMonthMax = perMonthStandard * 1.01; double[] PRperMonth = new double[totalmonth]; double[] PperMonth = new double[totalmonth]; double[] RperMonth = new double[totalmonth]; double[] PLeftperMonth = new double[totalmonth]; Map<Double, Double> lastCheckMap = new HashMap<Double, Double>(); Map<Double, double[]> PLeftperMonthMap = new HashMap<Double, double[]>(); Map<Double, double[]> PRperMonthMap = new HashMap<Double, double[]>(); Map<Double, double[]> PperMonthMap = new HashMap<Double, double[]>(); Map<Double, double[]> RperMonthMap = new HashMap<Double, double[]>(); Map<Double, Double> sumPRMap = new HashMap<Double, Double>(); Map<Double, Double> sumPMap = new HashMap<Double, Double>(); Map<Double, Double> sumRMap = new HashMap<Double, Double>(); if (IncreaseFlag == 1) { while (perMonthStandard < perMonthMax) { PRperMonth = new double[totalmonth]; PperMonth = new double[totalmonth]; RperMonth = new double[totalmonth]; PLeftperMonth = new double[totalmonth]; PRperMonth[0] = RepayUtils.num2second(perMonthStandard); PLeftperMonth[0] = RepayUtils.num2second(invest); RperMonth[0] = RepayUtils.num2secondDown(PLeftperMonth[0] * daysCount[0] * dateRate); PperMonth[0] = RepayUtils.num2second(PRperMonth[0] - RperMonth[0]); for (int j = 1; j < totalmonth; j++) { PRperMonth[j] = RepayUtils.num2second(perMonthStandard); PLeftperMonth[j] = RepayUtils.num2second(PLeftperMonth[j - 1] - PperMonth[j - 1]); RperMonth[j] = RepayUtils.num2secondDown(PLeftperMonth[j] * dateRate * daysCount[j]); PperMonth[j] = RepayUtils.num2second(PRperMonth[j] - RperMonth[j]); if (j == totalmonth - 1) { PperMonth[j] = RepayUtils.num2second(PLeftperMonth[j]); PRperMonth[j] = RepayUtils.num2second(PperMonth[j] + RperMonth[j]); } } double sumP = 0; double sumR = 0; double sumPR = 0; for (int i = 0; i < PLeftperMonth.length; i++) { sumP = sumP + PperMonth[i]; sumR = sumR + RperMonth[i]; sumPR = sumPR + PRperMonth[i]; } lastCheckMap.put(RepayUtils.num2second(perMonthStandard), Math.abs(PRperMonth[totalmonth - 1] - PRperMonth[totalmonth - 2])); PLeftperMonthMap.put(RepayUtils.num2second(perMonthStandard), PLeftperMonth); PRperMonthMap.put(RepayUtils.num2second(perMonthStandard), PRperMonth); PperMonthMap.put(RepayUtils.num2second(perMonthStandard), PperMonth); RperMonthMap.put(RepayUtils.num2second(perMonthStandard), RperMonth); sumPRMap.put(RepayUtils.num2second(perMonthStandard), RepayUtils.num2second(sumPR)); sumPMap.put(RepayUtils.num2second(perMonthStandard), RepayUtils.num2second(sumP)); sumRMap.put(RepayUtils.num2second(perMonthStandard), RepayUtils.num2second(sumR)); perMonthStandard = perMonthStandard + 0.01; } } Double resultKey = RepayUtils.getKeyByMinValue(lastCheckMap); // 当期剩余天数 int remainDaysCurPeriod = daysCount[curPeriod] - daysCurPeriod; double rebackPCurPeriod = RepayUtils.num2second( rebackInvest - RepayUtils.num2secondDown(PLeftperMonth[curPeriod] * dateRate * daysCurPeriod)); if (rebackPCurPeriod < PperMonthMap.get(resultKey)[curPeriod]) { // 还款小于当前期本金 PLeftperMonthMap.get(resultKey)[curPeriod] = RepayUtils .num2second(PLeftperMonthMap.get(resultKey)[curPeriod] - rebackPCurPeriod); PperMonthMap.get(resultKey)[curPeriod] = RepayUtils .num2second(PperMonthMap.get(resultKey)[curPeriod] - rebackPCurPeriod); RperMonthMap.get(resultKey)[curPeriod] = RepayUtils .num2secondDown(PLeftperMonthMap.get(resultKey)[curPeriod] * dateRate * remainDaysCurPeriod); PRperMonthMap.get(resultKey)[curPeriod] = RepayUtils .num2second(RperMonthMap.get(resultKey)[curPeriod] + PperMonthMap.get(resultKey)[curPeriod]); System.out.println("等额本息每月还款额:" + resultKey); System.out.println("每期经历" + Arrays.toString(daysCount)); System.out.println("每月余本金:" + Arrays.toString(PLeftperMonthMap.get(resultKey))); System.out.println("每月还款额:" + Arrays.toString(PRperMonthMap.get(resultKey))); System.out.println("每月还本金:" + Arrays.toString(PperMonthMap.get(resultKey))); System.out.println("每月还利息:" + Arrays.toString(RperMonthMap.get(resultKey))); double sumP = 0; double sumR = 0; double sumPR = 0; for (int i = 0; i < PLeftperMonth.length; i++) { sumP = sumP + PperMonthMap.get(resultKey)[i]; sumR = sumR + RperMonthMap.get(resultKey)[i]; sumPR = sumPR + PRperMonthMap.get(resultKey)[i]; } sumPRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumPR)); sumPMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumP)); sumRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumR)); System.out.println("总还款额:" + sumPRMap.get(resultKey)); System.out.println("总还本金:" + sumPMap.get(resultKey)); System.out.println("总还利息:" + sumRMap.get(resultKey)); } else { // 还款本金大于当期本金 int[] dayCountsAfter = new int[totalmonth - curPeriod]; double[] PRperMonthAfter = new double[totalmonth - curPeriod]; double[] PperMonthAfter = new double[totalmonth - curPeriod]; double[] RperMonthAfter = new double[totalmonth - curPeriod]; double[] PLeftperMonthAfter = new double[totalmonth - curPeriod]; // P本金0的阶段 第一个月 double remainInvest = RepayUtils.num2second(PLeftperMonthMap.get(resultKey)[curPeriod] - rebackPCurPeriod); PperMonthAfter[0] = RepayUtils.num2second(0); PLeftperMonthAfter[0] = remainInvest; RperMonthAfter[0] = RepayUtils.num2secondDown(PLeftperMonthAfter[0] * dateRate * remainDaysCurPeriod); PRperMonthAfter[0] = RperMonthAfter[0]; // P本金非0的再平衡阶段 int remainMonth = totalmonth - curPeriod - 1; double perMonthStandardRec = AverageCapitalPlusInterestUtils.getPerMonthPrincipalInterest(remainInvest, dateRate * 360, remainMonth); int[] daysCountRec = Arrays.copyOfRange(daysCount, curPeriod + 1, totalmonth); // 剩余天数数组 for (int i = 0; i < remainMonth; i++) { dayCountsAfter[i + 1] = daysCountRec[i]; dayCountsAfter[0] = remainDaysCurPeriod; } double perMonthMaxRec = perMonthStandardRec * 1.1; double[] PRperMonthRec = new double[remainMonth]; double[] PperMonthRec = new double[remainMonth]; double[] RperMonthRec = new double[remainMonth]; double[] PLeftperMonthRec = new double[remainMonth]; Map<Double, Double> lastCheckMapRec = new HashMap<Double, Double>(); Map<Double, double[]> PLeftperMonthMapRec = new HashMap<Double, double[]>(); Map<Double, double[]> PRperMonthMapRec = new HashMap<Double, double[]>(); Map<Double, double[]> PperMonthMapRec = new HashMap<Double, double[]>(); Map<Double, double[]> RperMonthMapRec = new HashMap<Double, double[]>(); while (perMonthStandardRec < perMonthMaxRec) { PRperMonthRec = new double[remainMonth]; PperMonthRec = new double[remainMonth]; RperMonthRec = new double[remainMonth]; PLeftperMonthRec = new double[remainMonth]; PRperMonthRec[0] = RepayUtils.num2second(perMonthStandardRec); PLeftperMonthRec[0] = RepayUtils.num2second(remainInvest); RperMonthRec[0] = RepayUtils.num2secondDown(PLeftperMonthRec[0] * daysCountRec[0] * dateRate); PperMonthRec[0] = RepayUtils.num2second(PRperMonthRec[0] - RperMonthRec[0]); for (int j = 1; j < remainMonth; j++) { PRperMonthRec[j] = RepayUtils.num2second(perMonthStandardRec); PLeftperMonthRec[j] = RepayUtils.num2second(PLeftperMonthRec[j - 1] - PperMonthRec[j - 1]); RperMonthRec[j] = RepayUtils.num2secondDown(PLeftperMonthRec[j] * dateRate * daysCountRec[j]); PperMonthRec[j] = RepayUtils.num2second(PRperMonthRec[j] - RperMonthRec[j]); if (j == remainMonth - 1) { PperMonthRec[j] = RepayUtils.num2second(PLeftperMonthRec[j]); PRperMonthRec[j] = RepayUtils.num2second(PperMonthRec[j] + RperMonthRec[j]); } } lastCheckMapRec.put(RepayUtils.num2second(perMonthStandardRec), Math.abs(PRperMonthRec[remainMonth - 1] - PRperMonthRec[remainMonth - 2])); PLeftperMonthMapRec.put(RepayUtils.num2second(perMonthStandardRec), PLeftperMonthRec); PRperMonthMapRec.put(RepayUtils.num2second(perMonthStandardRec), PRperMonthRec); PperMonthMapRec.put(RepayUtils.num2second(perMonthStandardRec), PperMonthRec); RperMonthMapRec.put(RepayUtils.num2secondDown(perMonthStandardRec), RperMonthRec); perMonthStandardRec = perMonthStandardRec + 0.01; } Double resultKeyRec = RepayUtils.getKeyByMinValue(lastCheckMapRec); for (int i = 1; i < totalmonth; i++) { PperMonthAfter[i] = RepayUtils.num2second(PperMonthMapRec.get(resultKeyRec)[i - 1]); PLeftperMonthAfter[i] = RepayUtils.num2second(PLeftperMonthMapRec.get(resultKeyRec)[i - 1]); RperMonthAfter[i] = RepayUtils.num2second(RperMonthMapRec.get(resultKeyRec)[i - 1]); PRperMonthAfter[i] = RepayUtils.num2second(PRperMonthMapRec.get(resultKeyRec)[i - 1]); } System.out.println("重新等额本息每月还款额:" + resultKeyRec); System.out.println("重新每期经历" + Arrays.toString(dayCountsAfter)); System.out.println("重新每月余本金:" + Arrays.toString(PLeftperMonthAfter)); System.out.println("重新每月还款额:" + Arrays.toString(PRperMonthAfter)); System.out.println("重新每月还本金:" + Arrays.toString(PperMonthAfter)); System.out.println("重新每月还利息:" + Arrays.toString(RperMonthAfter)); double sumP = 0; double sumR = 0; double sumPR = 0; for (int i = 0; i < PLeftperMonth.length; i++) { sumP = sumP + PperMonthAfter[i]; sumR = sumR + RperMonthAfter[i]; sumPR = sumPR + PRperMonthAfter[i]; } sumPRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumPR)); sumPMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumP)); sumRMap.put(RepayUtils.num2second(resultKey), RepayUtils.num2second(sumR)); System.out.println("总还款额:" + sumPRMap.get(resultKey)); System.out.println("总还本金:" + sumPMap.get(resultKey)); System.out.println("总还利息:" + sumRMap.get(resultKey)); } return resultKey; } }
借呗提前还款算法模拟
猜你喜欢
转载自huluyisheng.iteye.com/blog/2374727
今日推荐
周排行