在网上找蚂蚁借呗的计算方式,全是一堆计算不准确的算法,都是按整月来算的(每个月的天数不一样),但是蚂蚁借呗是按天算的,而且还是固定还款日,如我2月22日借款到3月10日还第一期,使用时间只有17天,所以每期的使用时间又不相同,但是又要求每期还款(本金+利息)尽量平均
以下是我自己琢磨的方法,唯一缺点是:在有一些数字是比借呗多一个0.01的平均数(误差)或少一个0.01的平均数(误差)
java
public static void main(String[] args){
mayiLend(new BigDecimal(Double.toString(10000)),new BigDecimal(Double.toString(0.00035)),new BigDecimal(Double.toString(3)));
}
static void mayiLend(final BigDecimal total, BigDecimal rate, BigDecimal period){//total总额 rate日利率 period期数
Calendar[] dates=new Calendar[period.intValue()];
Calendar now=Calendar.getInstance();
setTimeToMidnight(now);
int now_year = now.get(Calendar.YEAR);
int now_month = now.get(Calendar.MONTH);
int now_day = now.get(Calendar.DAY_OF_MONTH);
int year=now_year;
int month=now_month;
int day=10;//每月10号
Repayment repays[]=new Repayment[period.intValue()];//保存每期还款信息
for(int i=0;i<period.intValue();i++){
repays[i]=new Repayment();
if(++month>11){
month=0;
year++;
}
Calendar c=Calendar.getInstance();
setTimeToMidnight(c);
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, month);
c.set(Calendar.DAY_OF_MONTH, day);
dates[i]=c;
}
BigDecimal average=total.divide(period,2, BigDecimal.ROUND_DOWN);//平均每月还款,最开始设为贷款总额/期数
BigDecimal remain=null;//剩余未还的
BigDecimal step=new BigDecimal(Double.toString(0.01));
do {
if(remain!=null) {
average = average.add(remain.divide(period, 2, BigDecimal.ROUND_DOWN));//平均还款=平均还款(上次)+(剩余(上次)/期数) 保留两位小数点
}
remain = total;
long lastTime = now.getTimeInMillis();
for (int i = 0; i < period.intValue(); i++) {
long rePlayTime = dates[i].getTimeInMillis();//还款时间
BigDecimal days = new BigDecimal(Double.toString(millisecondsToDays(rePlayTime - lastTime)));//计算与上一次还款日间隔(天数)
BigDecimal interest =days.multiply(rate).multiply(remain).setScale(2,BigDecimal.ROUND_DOWN);//计算当期利息,天数*日利率*剩余未还金额
BigDecimal principal = average.subtract(interest);
repays[i].date=dates[i];
repays[i].interest =interest;
repays[i].principal =principal;
remain=remain.subtract(principal);
if(i==period.intValue()-1){//最后一次还款加上(或减)余数
repays[i].principal =repays[i].principal.add(remain);
}
repays[i].payment =interest.add(repays[i].principal);
lastTime = rePlayTime;
}
}while(remain.abs().compareTo(step.multiply(period))>=0);//如果剩余未还的绝对值大于等于(期数*0.01),则继续分割
for(int i=0;i<period.intValue();i++){
Repayment repay=repays[i];
System.out.println("第"+(i+1)+"期 时间:"+repay.date.get(Calendar.YEAR)+"年"+(repay.date.get(Calendar.MONTH)+1)+"月"
+repay.date.get(Calendar.DAY_OF_MONTH)+"日 还款:"+repay.payment+" = 本金:"+repays[i].principal +" + 利息:"+repays[i].interest);
}
}
static class Repayment {
Calendar date;
BigDecimal interest;
BigDecimal principal;
BigDecimal payment;
}
static void setTimeToMidnight(Calendar calendar) {//设置每天12点0分0秒为分割点
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
}
static int millisecondsToDays(long intervalMs) {//计算天数
return (int) (intervalMs / (1000 * 86400));
}在这里插入代码片
测试
mayiLend(new BigDecimal(Double.toString(10000)),new BigDecimal(Double.toString(0.00035)),new BigDecimal(Double.toString(3)));
打印
第1期 时间:2020年3月10日 还款:3389.02 = 本金:3329.52 + 利息:59.50
第2期 时间:2020年4月10日 还款:3389.02 = 本金:3316.65 + 利息:72.37
第3期 时间:2020年5月10日 还款:3389.04 = 本金:3353.83 + 利息:35.21
对比借呗
但是如果把代款额度改为10008
mayiLend(new BigDecimal(Double.toString(10008)),new BigDecimal(Double.toString(0.00035)),new BigDecimal(Double.toString(3)));
打印
第1期 时间:2020年3月10日 还款:3391.73 = 本金:3332.19 + 利息:59.54
第2期 时间:2020年4月10日 还款:3391.73 = 本金:3319.30 + 利息:72.43
第3期 时间:2020年5月10日 还款:3391.75 = 本金:3356.51 + 利息:35.24
这时借呗
这里就对不上了,原因是估值平均还款少了一个0.01,但搞不懂借呗是怎么判断还要再加估值平均值的,
有时还乘0.02会在最后一次还款上补全,有时又是最后一次减去多还的