贷款计算公式——java实现

废话说在前头,本人公司做银行APP,每次写到贷款计算器总是一遍又一遍研究计算公式。N次过后,还是决定写一篇blog分享给大家。

:利率一律按照4.9计算。所有计算结果参照在线贷款计算公式

1 等额本息

每月还款本金+利息一样。
贷款本金100万,贷款期限30年,贷款利息91万元(近似值),那么月供191万元/360月。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 /**
* 计算等额本息还款
*
* @param principal 贷款总额
* @param months 贷款期限
* @param rate 贷款利率
* @return
*/
public static String[] calculateEqualPrincipalAndInterest(double principal, int months, double rate) {
ArrayList<String> data = new ArrayList<String>();
double monthRate = rate / (100 * 12);//月利率
double preLoan = (principal * monthRate * Math.pow((1 + monthRate), months)) / (Math.pow((1 + monthRate), months) - 1);//每月还款金额
double totalMoney = preLoan * months;//还款总额
double interest = totalMoney - principal;//还款总利息
data.add(FORMAT.format(totalMoney));//还款总额
data.add(FORMAT.format(principal));//贷款总额
data.add(FORMAT.format(interest));//还款总利息
data.add(FORMAT.format(preLoan));//每月还款金额
data.add(String.valueOf(months));//还款期限
return data.toArray(new String[data.size()]);
}

运行结果:

在线计算结果:

2 等额本金

贷款本金100万,贷款期限30年。每月还款本金=100万/360月,每月还款利息=剩余贷款金额*月利率。所以每月利息递减。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 计算等额本金还款
*
* @param principal 贷款总额
* @param months 贷款期限
* @param rate 贷款利率
* @return
*/
public static String[] calculateEqualPrincipal(double principal, int months, double rate) {
ArrayList<String> data = new ArrayList<String>();
double monthRate = rate / (100 * 12);//月利率
double prePrincipal = principal / months;//每月还款本金
double firstMonth = prePrincipal + principal * monthRate;//第一个月还款金额
double decreaseMonth = prePrincipal * monthRate;//每月利息递减
double interest = (months + 1) * principal * monthRate / 2;//还款总利息
double totalMoney = principal + interest;//还款总额
data.add(FORMAT.format(totalMoney));//还款总额
data.add(FORMAT.format(principal));//贷款总额
data.add(FORMAT.format(interest));//还款总利息
data.add(FORMAT.format(firstMonth));//首月还款金额
data.add(FORMAT.format(decreaseMonth));//每月递减利息
data.add(String.valueOf(months));//还款期限
return data.toArray(new String[data.size()]);
}

运行结果:

在线计算结果:

3 提前还款

当客户有足够的钱偿还贷款本金时,可以向银行申请提前还款。

3.1 全部提前还款

一次性结清贷款

3.1.1 等额本息

扣除之前每月还款的本金(前期还款时,利息占月供很大的比例),剩余贷款金额加上一个月利息即支付金额。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* 一次性提前还款计算(等额本息)
*
* @param principal 贷款总额
* @param months 贷款期限
* @param payTimes 已还次数
* @param rate 贷款利率
* @return
*/
public static String[] calculateEqualPrincipalAndInterest(double principal, int months, int payTimes, double rate) {
ArrayList<String> data = new ArrayList<String>();
double monthRate = rate / (100 * 12);//月利率
double preLoan = (principal * monthRate * Math.pow((1 + monthRate), months)) / (Math.pow((1 + monthRate), months) - 1);//每月还款金额
double totalMoney = preLoan * months;//还款总额
double interest = totalMoney - principal;//还款总利息
double leftLoan = principal * Math.pow(1 + monthRate, payTimes) - preLoan * (Math.pow(1 + monthRate, payTimes) - 1) / monthRate;//n个月后欠银行的钱
double payLoan = principal - leftLoan;//已还本金
double payTotal = preLoan * payTimes;//已还总金额
double payInterest = payTotal - payLoan;//已还利息
double totalPayAhead = leftLoan * (1 + monthRate);//剩余一次还清
double saveInterest = totalMoney - payTotal - totalPayAhead;
data.add(FORMAT.format(totalMoney));//原还款总额
data.add(FORMAT.format(principal));//贷款总额
data.add(FORMAT.format(interest));//原还款总利息
data.add(FORMAT.format(preLoan));//原还每月还款金额
data.add(FORMAT.format(payTotal));//已还总金额
data.add(FORMAT.format(payLoan));//已还本金
data.add(FORMAT.format(payInterest));//已还利息
data.add(FORMAT.format(totalPayAhead));//一次还清支付金额
data.add(FORMAT.format(saveInterest));//节省利息
data.add(String.valueOf(0));//剩余还款期限
return data.toArray(new String[data.size()]);
}

已还款10次,运行结果:

在线计算运行结果:

由此可以看出,前10次还款,扣除本金只占20%左右。

3.1.2 等额本金

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* 一次性提前还款计算(等额本金)
*
* @param principal 贷款总额
* @param months 贷款期限
* @param payTimes 已还次数
* @param rate 贷款利率
* @return
*/
public static String[] calculateEqualPrincipal(double principal, int months, int payTimes, double rate) {
ArrayList<String> data = new ArrayList<String>();
double monthRate = rate / (100 * 12);//月利率
double prePrincipal = principal / months;//每月还款本金
double firstMonth = prePrincipal + principal * monthRate;//第一个月还款金额
double decreaseMonth = prePrincipal * monthRate;//每月利息递减
double interest = (months + 1) * principal * monthRate / 2;//还款总利息
double totalMoney = principal + interest;//还款总额
double payLoan = prePrincipal * payTimes;//已还本金
double payInterest = (principal * payTimes - prePrincipal * (payTimes - 1) * payTimes / 2) * monthRate;//已还利息
double payTotal = payLoan + payInterest;//已还总额
double totalPayAhead = (principal - payLoan) * (1 + monthRate);//提前还款金额(剩余本金加上剩余本金当月利息)
double saveInterest = totalMoney - payTotal - totalPayAhead;
data.add(FORMAT.format(totalMoney));//原还款总额
data.add(FORMAT.format(principal));//贷款总额
data.add(FORMAT.format(interest));//原还款总利息
data.add(FORMAT.format(firstMonth));//原首月还款金额
data.add(FORMAT.format(decreaseMonth));//原每月递减利息
data.add(FORMAT.format(payTotal));//已还总金额
data.add(FORMAT.format(payLoan));//已还本金
data.add(FORMAT.format(payInterest));//已还利息
data.add(FORMAT.format(totalPayAhead));//一次还清支付金额
data.add(FORMAT.format(saveInterest));//节省利息
data.add(String.valueOf(0));//剩余还款期限
return data.toArray(new String[data.size()]);
}

已还款10次,运行结果:

在线计算运行结果:

对比等额本息,已偿还本金占还款金额30%左右。

3.2 部分提前还款

3.2.1 保持月供不变

3.2.1.1 等额本息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    /**
* 部分提前还款计算(等额本息、月供不变)
*
* @param principal 贷款总额
* @param months 贷款期限
* @param aheadPrincipal 提前还款金额
* @param payTimes 已还次数
* @param rate 贷款利率
* @return
*/
public static String[] calculateEqualPrincipalAndInterestApart(double principal, int months, double aheadPrincipal, int payTimes, double rate) {
ArrayList<String> data = new ArrayList<String>();
double monthRate = rate / (100 * 12);//月利率
double preLoan = (principal * monthRate * Math.pow((1 + monthRate), months)) / (Math.pow((1 + monthRate), months) - 1);//每月还款金额
double totalMoney = preLoan * months;//还款总额
double interest = totalMoney - principal;//还款总利息
double leftLoanBefore = principal * Math.pow(1 + monthRate, payTimes) - preLoan * (Math.pow(1 + monthRate, payTimes) - 1) / monthRate;//提前还款前欠银行的钱
double leftLoan = principal * Math.pow(1 + monthRate, payTimes + 1) - preLoan * (Math.pow(1 + monthRate, payTimes + 1) - 1) / monthRate-aheadPrincipal;//提前还款后欠银行的钱
double payLoan = principal - leftLoanBefore;//已还本金
double payTotal = preLoan * payTimes ;//已还总金额
double payInterest = payTotal - payLoan;//已还利息
double aheadTotalMoney = aheadPrincipal + preLoan;//提前还款总额
//计算剩余还款期限
int leftMonth = (int) Math.floor(Math.log(preLoan / (preLoan - leftLoan * monthRate)) / Math.log(1 + monthRate));
double newPreLoan = (leftLoan * monthRate * Math.pow((1 + monthRate), leftMonth)) / (Math.pow((1 + monthRate), leftMonth) - 1);//剩余贷款每月还款金额
double leftTotalMoney = newPreLoan * leftMonth;//剩余还款总额
double leftInterest = leftTotalMoney - (leftLoan-aheadPrincipal);
double saveInterest = totalMoney - aheadTotalMoney - leftTotalMoney-payTotal;
data.add(FORMAT.format(totalMoney));//原还款总额
data.add(FORMAT.format(principal));//贷款总额
data.add(FORMAT.format(interest));//原还款总利息
data.add(FORMAT.format(preLoan));//原还每月还款金额
data.add(FORMAT.format(payTotal));//已还总金额
data.add(FORMAT.format(payLoan));//已还本金
data.add(FORMAT.format(payInterest));//已还利息
data.add(FORMAT.format(aheadTotalMoney));//提前还款总额
data.add(FORMAT.format(leftTotalMoney));//剩余还款总额
data.add(FORMAT.format(leftInterest));//剩余还款总利息
data.add(FORMAT.format(newPreLoan));//剩余每月还款金额
data.add(FORMAT.format(saveInterest));//节省利息
data.add(String.valueOf(leftMonth));//剩余还款期限
return data.toArray(new String[data.size()]);
}

贷款100万,提前还款50万。首次还款:17年8月,提前还款:18年6月。已还次数10次是截止到18年5月。剩余贷款,保持月供不变(大致维持不变),后续需还款114期(9年零6月),所以提前还款后还款日期:18年7月~27年12月。

运行结果:

在线计算结果:(这里有1个月的误差

3.2.1.2 等额本金
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* 部分提前还款计算(等额本金、月供不变)
* @param principal 贷款总额
* @param months 贷款期限
* @param aheadPrincipal 提前还款金额
* @param payTimes 已还次数
* @param rate 贷款利率
* @return
*/
public static String[] calculateEqualPrincipalApart(double principal, int months, double aheadPrincipal, int payTimes, double rate) {
ArrayList<String> data = new ArrayList<String>();
double monthRate = rate / (100 * 12);//月利率
double prePrincipal = principal / months;//每月还款本金
double firstMonth = prePrincipal + principal * monthRate;//第一个月还款金额
double decreaseMonth = prePrincipal * monthRate;//每月利息递减
double interest = (months + 1) * principal * monthRate / 2;//还款总利息
double totalMoney = principal + interest;//还款总额
double payLoan = prePrincipal * payTimes;//已还本金
double payInterest = (principal * payTimes - prePrincipal * (payTimes - 1) * payTimes / 2) * monthRate;//已还利息
double payTotal = payLoan + payInterest;//已还总额
double aheadTotalMoney = (principal - payLoan) * monthRate+aheadPrincipal+prePrincipal;//提前还款金额
double leftLoan = principal - aheadPrincipal - payLoan-prePrincipal;//剩余金额
int leftMonth = (int) Math.floor(leftLoan / prePrincipal);
double newPrePrincipal = leftLoan / leftMonth;//新的每月还款本金
double newFirstMonth = newPrePrincipal + leftLoan * monthRate;//新的第一个月还款金额
double newDecreaseMonth = newPrePrincipal * monthRate;//新的每月利息递减
double leftInterest = (leftMonth + 1) * leftLoan * monthRate / 2;//还款总利息
double leftTotalMoney = leftLoan + leftInterest;//还款总额
double saveInterest = totalMoney-payTotal-aheadTotalMoney-leftTotalMoney;
data.add(FORMAT.format(totalMoney));//原还款总额
data.add(FORMAT.format(principal));//贷款总额
data.add(FORMAT.format(interest));//原还款总利息
data.add(FORMAT.format(firstMonth));//原还首月还款金额
data.add(FORMAT.format(decreaseMonth));//原每月递减利息
data.add(FORMAT.format(payTotal));//已还总金额
data.add(FORMAT.format(payLoan));//已还本金
data.add(FORMAT.format(payInterest));//已还利息
data.add(FORMAT.format(aheadTotalMoney));//提前还款总额
data.add(FORMAT.format(leftTotalMoney));//剩余还款总额
data.add(FORMAT.format(leftInterest));//剩余还款总利息
data.add(FORMAT.format(newFirstMonth));//剩余首月还款金额
data.add(FORMAT.format(newDecreaseMonth));//剩余月递减利息
data.add(FORMAT.format(saveInterest));//节省利息
data.add(String.valueOf(leftMonth));//剩余还款期限
return data.toArray(new String[data.size()]);
}

贷款100万,还款10期后,提前还款50万。

运行结果:

在线计算结果:

3.2.2 保持期数不变

3.2.2.1 等额本息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* 部分提前还款计算(等额本息、期限不变)
* @param principal 贷款总额
* @param months 贷款期限
* @param aheadPrincipal 提前还款金额
* @param payTimes 已还次数
* @param rate 贷款利率
* @return
*/
public static String[] calculateEqualPrincipalAndInterestApart2(double principal, int months, double aheadPrincipal, int payTimes, double rate) {
ArrayList<String> data = new ArrayList<String>();
double monthRate = rate / (100 * 12);//月利率
double preLoan = (principal * monthRate * Math.pow((1 + monthRate), months)) / (Math.pow((1 + monthRate), months) - 1);//每月还款金额
double totalMoney = preLoan * months;//还款总额
double interest = totalMoney - principal;//还款总利息
double leftLoanBefore = principal * Math.pow(1 + monthRate, payTimes ) - preLoan * (Math.pow(1 + monthRate, payTimes ) - 1) / monthRate;//提前还款前欠银行的钱
double leftLoan = principal * Math.pow(1 + monthRate, payTimes + 1) - preLoan * (Math.pow(1 + monthRate, payTimes + 1) - 1) / monthRate;//提前还款后银行的钱
double payLoan = principal - leftLoanBefore;//已还本金
double payTotal = preLoan * payTimes;//已还总金额
double payInterest = payTotal - payLoan;//已还利息
double aheadTotalMoney = preLoan + aheadPrincipal;//下个月还款金额
double newPreLoan = ((leftLoan - aheadPrincipal) * monthRate * Math.pow((1 + monthRate), months - payTimes - 1)) / (Math.pow((1 + monthRate), months - payTimes - 1) - 1);//下个月起每月还款金额
double leftTotalMoney = newPreLoan*(months-payTimes);
double leftInterest =leftTotalMoney -(leftLoan - aheadPrincipal);
double saveInterest = totalMoney-payTotal-aheadTotalMoney-leftTotalMoney;
data.add(FORMAT.format(totalMoney));//原还款总额
data.add(FORMAT.format(principal));//贷款总额
data.add(FORMAT.format(interest));//原还款总利息
data.add(FORMAT.format(preLoan));//原还每月还款金额
data.add(FORMAT.format(payTotal));//已还总金额
data.add(FORMAT.format(payLoan));//已还本金
data.add(FORMAT.format(payInterest));//已还利息
data.add(FORMAT.format(aheadTotalMoney));//提前还款总额
data.add(FORMAT.format(leftTotalMoney));//剩余还款总额
data.add(FORMAT.format(leftInterest));//剩余还款总利息
data.add(FORMAT.format(newPreLoan));//剩余每月还款金额
data.add(FORMAT.format(saveInterest));//节省利息
data.add(String.valueOf(months));//剩余还款期限
return data.toArray(new String[data.size()]);
}

运行结果:

在线计算结果:

3.2.2.2 等额本金
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* 部分提前还款计算(等额本金、期限不变)
* @param principal 贷款总额
* @param months 贷款期限
* @param aheadPrincipal 提前还款金额
* @param payTimes 已还次数
* @param rate 贷款利率
* @return
*/
public static String[] calculateEqualPrincipalApart2(double principal, int months, double aheadPrincipal, int payTimes, double rate) {
ArrayList<String> data = new ArrayList<String>();
double monthRate = rate / (100 * 12);//月利率
double prePrincipal = principal / months;//每月还款本金
double firstMonth = prePrincipal + principal * monthRate;//第一个月还款金额
double decreaseMonth = prePrincipal * monthRate;//每月利息递减
double interest = (months + 1) * principal * monthRate / 2;//还款总利息
double totalMoney = principal + interest;//还款总额
double payLoan = prePrincipal * payTimes;//已还本金
double payInterest = (principal * payTimes - prePrincipal * (payTimes - 1) * payTimes / 2) * monthRate;//已还利息
double payTotal = payLoan + payInterest;//已还总额
double aheadTotalMoney = (principal - payLoan) * monthRate+aheadPrincipal+prePrincipal;//提前还款金额
int leftMonth = months - payTimes-1;
double leftLoan = principal - aheadPrincipal - payLoan-prePrincipal;
double newPrePrincipal = leftLoan / leftMonth;//新的每月还款本金
double newFirstMonth = newPrePrincipal + leftLoan * monthRate;//新的第一个月还款金额
double newDecreaseMonth = newPrePrincipal * monthRate;//新的每月利息递减
double leftInterest = (leftMonth + 1) * leftLoan * monthRate / 2;//还款总利息
double leftTotalMoney = leftLoan + leftInterest;//还款总额
double saveInterest = totalMoney-payTotal-aheadTotalMoney-leftTotalMoney;
data.add(FORMAT.format(totalMoney));//原还款总额
data.add(FORMAT.format(principal));//贷款总额
data.add(FORMAT.format(interest));//原还款总利息
data.add(FORMAT.format(firstMonth));//原还首月还款金额
data.add(FORMAT.format(decreaseMonth));//原每月递减利息
data.add(FORMAT.format(payTotal));//已还总金额
data.add(FORMAT.format(payLoan));//已还本金
data.add(FORMAT.format(payInterest));//已还利息
data.add(FORMAT.format(aheadTotalMoney));//提前还款总额
data.add(FORMAT.format(leftTotalMoney));//剩余还款总额
data.add(FORMAT.format(leftInterest));//剩余还款总利息
data.add(FORMAT.format(newFirstMonth));//剩余首月还款金额
data.add(FORMAT.format(newDecreaseMonth));//剩余月递减利息
data.add(FORMAT.format(saveInterest));//节省利息
data.add(String.valueOf(months));//剩余还款期限
return data.toArray(new String[data.size()]);
}

运行结果:

在线计算结果:

测试数据:

  • 贷款100万
  • 部分提前还款50万
  • 已偿还10期
  • 贷款利率4.9
  • 贷款期限30年
  • 觉得有用?那打赏一个呗。[去打赏](/donate/)

    Author: flueky
    Link: http://example.com/231/
    Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.