一般信用贷款会提供两种还款方式:每月等额或者先息后本。每月等额,就是每月归还等同的部分本金和利息,你手里在使用的本金其实是逐月减少的。先息后本就是先还利息,到期归还本金。

每月等额



1 import java.math.BigDecimal;
 2 import java.util.Calendar;
 3 import java.util.Date;
 4 
 5 /**
 6  * <p>Title: 等额本息还款工具类</p>
 7  *
 8  */
 9 public class CPMUtils{
10 
11     /**
12      * <p>Description: 每月还款总额。〔贷款本金×月利率×(1+月利率)^还款月数〕÷〔(1+月利率)^还款月数-1〕</p>
13      * @param principal 贷款本金
14      * @param monthlyInterestRate 月利率
15      * @param amount 期数
16      * @return
17      */
18     public static BigDecimal monthlyRepayment(BigDecimal principal, BigDecimal monthlyInterestRate, int amount){
19         //(1+月利率)^还款月数
20         BigDecimal temp = monthlyInterestRate.add(MoneyUtils.ONE).pow(amount);
21         return principal.multiply(monthlyInterestRate)
22                         .multiply(temp)
23                         .divide(temp.subtract(MoneyUtils.ONE), MoneyUtils.MATHCONTEXT);
24     }
25     
26     /**
27      * <p>Description: 月还款利息。(贷款本金×月利率-月还款额)*(1+月利率)^(当前期数-1)+月还款额</p>
28      * @param principal 贷款本金
29      * @param monthlyInterestRate 月利率
30      * @param monthlyRepayment 月还款额
31      * @param number 当前期数
32      * @return
33      */
34     public static BigDecimal monthlyInterest(BigDecimal principal, BigDecimal monthlyInterestRate, BigDecimal monthlyRepayment, int number){
35         //(1+月利率)^(当前期数-1)
36         BigDecimal temp = monthlyInterestRate.add(MoneyUtils.ONE).pow(number - 1);
37         return principal.multiply(monthlyInterestRate)
38                         .subtract(monthlyRepayment)
39                         .multiply(temp).add(monthlyRepayment, MoneyUtils.MATHCONTEXT);
41     }
42     
43     /**
44      * <p>Description: 还款总利息。期数×贷款本金×月利率×(1+月利率)^期数÷〔(1+月利率)^期数-1〕-贷款本金 </p>
45      * @param principal 贷款本金
46      * @param monthlyInterestRate 月利率
47      * @param amount 还款期数
48      * @return
49      */
50     public static BigDecimal interest(BigDecimal principal, BigDecimal monthlyInterestRate, int amount){
51         //(1+月利率)^期数
52         BigDecimal temp = monthlyInterestRate.add(MoneyUtils.ONE).pow(amount);
53         return new BigDecimal(amount)
54                    .multiply(principal)
55                    .multiply(monthlyInterestRate)
56                    .multiply(temp)
57                    .divide(temp.subtract(MoneyUtils.ONE), MoneyUtils.MATHCONTEXT)
58                    .subtract(principal, MoneyUtils.MATHCONTEXT);
59     }
60     
61     /**
62      * <p>Description: 月还款本金。已经精确到分位,未做单位换算</p>
63      * @param principal 贷款本金
64      * @param monthlyInterestRate 月利率
65      * @param monthlyRepayment 月还款额
66      * @param number 当前期数
67      * @return
68      */
69     public static BigDecimal monthlyPrincipal(BigDecimal principal, BigDecimal monthlyInterestRate, BigDecimal monthlyRepayment, int number){
70         BigDecimal monthInterest = monthlyInterest(principal, monthlyInterestRate, monthlyRepayment, number);
71         //月还款额-月还款利息
72         return monthlyRepayment.subtract(monthInterest).setScale(MoneyUtils.MONEYSHOWSCALE, MoneyUtils.SAVEROUNDINGMODE);
73     }
74     
75     /**
76      * <p>Description: 月还款本金。已经精确到分位,未做单位换算</p>
77      * @param monthRepayment 月还款总额
78      * @param monthInterest 月还款利息
79      * @return
80      */
81     public static BigDecimal monthPrincipal(BigDecimal monthRepayment, BigDecimal monthInterest){
82         //月还款总额-月还款利息
83         return monthRepayment.subtract(monthInterest).setScale(MoneyUtils.MONEYSHOWSCALE, MoneyUtils.SAVEROUNDINGMODE);
84     }
85 
86 }



 

   先息后本

 



1  import java.math.BigDecimal;
 2 
 3   /**
 4   * <p>Title: 先息后本还款方式工具类型</p>
 5   */
 6   public class BIAPPUtils extends RepaymentUtils {
 7 
 8     /**
 9     * <p>Description: 月还款利息  贷款本金×月利率 </p>
10     * @param loan 贷款本金
11     * @param monthlyInterestRate 月利率
12     * @return
13     */
14     public static BigDecimal monthlyInterest(BigDecimal loan, BigDecimal monthlyInterestRate){
15       return loan.multiply(monthlyInterestRate, MoneyUtils.MATHCONTEXT);
16     }
17     /**
18     * <p>Description: 还款总利息  贷款本金×月利率×期数</p>
19     * @param loan 贷款本金
20     * @param monthlyInterestRate 月利率
21     * @param number 期数
22     * @return
23     */
24     public static BigDecimal interest(BigDecimal loan, BigDecimal monthlyInterestRate, int number){
25       return loan.multiply(monthlyInterestRate).multiply(new BigDecimal(number), MoneyUtils.MATHCONTEXT);
26     }
27     /**
28     * <p>Description: 月还款额</p>
29     * @param loan 贷款本金
30     * @param monthlyInterestRate 月利率
31     * @param amount 期数
32     * @param curNumber 当前期数
33     * @return
34     */
35     public static BigDecimal monthlyRepayment(BigDecimal loan, BigDecimal monthlyInterestRate, int amount, int curNumber){
36         BigDecimal monthlyInterest = monthlyInterest(loan, monthlyInterestRate);
37         if(amount == curNumber){
38           return monthlyInterest.add(loan, MoneyUtils.MATHCONTEXT);//最后月还款额
39         }else{
40           return monthlyInterest;
41         }
42     }
43   }



 

  *金额计算工具类

 



1  import java.math.BigDecimal;
  2   import java.math.MathContext;
  3   import java.math.RoundingMode;
  4   import java.text.NumberFormat;
  5 
  6   public class MoneyUtils {
  7     /**
  8     * 标度(小数位数)
  9     */
 10     public static final int SCALE = 10;
 11 
 12     /**
 13     * 金钱显示标度(小数位数)
 14     */
 15     public static final int MONEYSHOWSCALE = 2;
 16 
 17     /**
 18     * 利率显示标度(小数位数)
 19     */
 20     public static final int INTERESTRATESHOWSCALE = 4;
 21 
 22     /**
 23     * 精度
 24     */
 25     public static final int PRECISION = 30;
 26 
 27     /**
 28     * 保存舍入规则
 29     */
 30     public static final RoundingMode SAVEROUNDINGMODE = RoundingMode.HALF_UP;
 31 
 32     /**
 33     * 是否舍去小数点最后的零
 34     */
 35     public static boolean STRIPTRAILINGZEROS = true;
 36 
 37     /**
 38     * 运算上下文(设置精度、舍入规则)
 39     */
 40     public static final MathContext MATHCONTEXT = new MathContext(PRECISION, SAVEROUNDINGMODE);
 41 
 42     /**
 43     * 每年天数
 44     */
 45     public static final String YEARDAYS = "360";
 46 
 47     /**
 48     * 每年月数
 49     */
 50     public static final String YEARMOTHS = "12";
 51 
 52     /**
 53     * 每月天数
 54     */
 55     public static final String MOTHDAYS = "30";
 56 
 57     /**
 58     * 数字“1”
 59     */
 60     public static final BigDecimal ONE = new BigDecimal(1);
 61 
 62     /**
 63     * 数字“100”
 64     */
 65     public static final BigDecimal HUNDRED = new BigDecimal(100);
 66 
 67     /**
 68     * 数字“0.01”
 69     */
 70     public static final BigDecimal ONEHUNDREDTH = new BigDecimal(0.01);
 71 
 72     public static BigDecimal newBigDecimal(String str){
 73       return (str == null || str.trim().isEmpty()) ? BigDecimal.ZERO : new BigDecimal(str);
 74     }
 75 
 76     /**
 77     * <p>Description: 加法返回格式化结果数字</p>
 78     * @param addend
 79     * @param augend
 80     * @return
 81     */
 82     public static BigDecimal add(BigDecimal addend, BigDecimal augend){
 83       return formatMoney(addend.add(augend, MATHCONTEXT));
 84     }
 85 
 86       /**
 87     * <p>Description: 加法返回格式化结果数字</p>
 88     * @param addend
 89     * @param augend
 90     * @return
 91     */
 92     public static BigDecimal add(String addend, String augend){
 93       BigDecimal decimalAddend = newBigDecimal(addend);
 94       BigDecimal decimalAugend = newBigDecimal(augend);
 95       return formatMoney(decimalAddend.add(decimalAugend, MATHCONTEXT));
 96     }
 97 
 98     /**
 99     * <p>Description: 加法返回格式化结果字符串</p>
100     * @param addend
101     * @param augend
102     * @return
103     */
104     public static String addToString(BigDecimal addend, BigDecimal augend){
105       return formatToString(addend.add(augend, MATHCONTEXT));
106     }
107 
108     /**
109     * <p>Description: 加法返回格式化结果字符串</p>
110     * @param addend
111     * @param augend
112     * @return
113     */
114     public static String addToString(String addend, String augend){
115       BigDecimal decimalAddend = newBigDecimal(addend);
116       BigDecimal decimalAugend = newBigDecimal(augend);
117       return formatToString(decimalAddend.add(decimalAugend, MATHCONTEXT));
118     }
119 
120     /**
121     * <p>Description: 减法返回格式化结果数字</p>
122     * @param minuend
123     * @param subtrahend
124     * @return
125     */
126     public static BigDecimal subtract(BigDecimal minuend, BigDecimal subtrahend){
127       return formatMoney(minuend.subtract(subtrahend, MATHCONTEXT));
128     }
129 
130 
131     /**
132     * <p>Description: 减法返回格式化结果数字</p>
133     * @param minuend
134     * @param subtrahend
135     * @return
136     */
137     public static BigDecimal subtract(String minuend, String subtrahend){
138       BigDecimal decimalMinuend = newBigDecimal(minuend);
139       BigDecimal decimalSubtrahend = newBigDecimal(subtrahend);
140       return formatMoney(decimalMinuend.subtract(decimalSubtrahend, MATHCONTEXT));
141     }
142 
143     /**
144     * <p>Description: 减法返回格式化结果字符串</p>
145     * @param minuend
146     * @param subtrahend
147     * @return
148     */
149     public static String subtractToString(BigDecimal minuend, BigDecimal subtrahend){
150       return formatToString(minuend.subtract(subtrahend, MATHCONTEXT));
151     }
152     /**
153     * <p>Description: 减法返回格式化结果字符串</p>
154     * @param minuend
155     * @param subtrahend
156     * @return
157     */
158     public static String subtractToString(String minuend, String subtrahend){
159       BigDecimal decimalMinuend = newBigDecimal(minuend);
160       BigDecimal decimalSubtrahend = newBigDecimal(subtrahend);
161       return formatToString(decimalMinuend.subtract(decimalSubtrahend, MATHCONTEXT));
162     }
163 
164     /**
165     * <p>Description: 乘法返回格式化结果数字</p>
166     * @param multiplier
167     * @param multiplicand
168     * @return
169     */
170     public static BigDecimal multiply(BigDecimal multiplier, BigDecimal multiplicand){
171       return formatMoney(multiplier.multiply(multiplicand, MATHCONTEXT));
172     }
173 
174 
175     /**
176     * <p>Description: 乘法返回格式化结果数字</p>
177     * @param multiplier
178     * @param multiplicand
179     * @return
180     */
181     public static BigDecimal multiply(String multiplier, String multiplicand){
182       BigDecimal decimalMultiplier = newBigDecimal(multiplier);
183       BigDecimal decimalMultiplicand = newBigDecimal(multiplicand);
184       return formatMoney(decimalMultiplier.multiply(decimalMultiplicand, MATHCONTEXT));
185     }
186 
187     /**
188     * <p>Description: 乘法返回格式化结果字符串</p>
189     * @param multiplier
190     * @param multiplicand
191     * @return
192     */
193     public static String multiplyToString(BigDecimal multiplier, BigDecimal multiplicand){
194       return formatToString(multiplier.multiply(multiplicand, MATHCONTEXT));
195     }
196     /**
197     * <p>Description: 乘法返回格式化结果字符串</p>
198     * @param multiplier
199     * @param multiplicand
200     * @return
201     */
202     public static String multiplyToString(String multiplier, String multiplicand){
203       BigDecimal decimalMultiplier = newBigDecimal(multiplier);
204       BigDecimal decimalMultiplicand = newBigDecimal(multiplicand);
205       return formatToString(decimalMultiplier.multiply(decimalMultiplicand, MATHCONTEXT));
206     }
207 
208     /**
209     * <p>Description: 除法返回格式化结果数字</p>
210     * @param dividend
211     * @param divisor
212     * @return
213     */
214     public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor){
215       return formatMoney(dividend.divide(divisor, MATHCONTEXT));
216     }
217     /**
218     * <p>Description: 除法返回格式化结果数字</p>
219     * @param dividend
220     * @param divisor
221     * @return
222     */
223     public static BigDecimal divide(String dividend, String divisor){
224       BigDecimal decimalDividend = newBigDecimal(dividend);
225       BigDecimal decimalDivisor = newBigDecimal(divisor);
226       return formatMoney(decimalDividend.divide(decimalDivisor, MATHCONTEXT));
227     }
228 
229     /**
230     * <p>Description: 除法返回格式化结果字符串</p>
231     * @param dividend
232     * @param divisor
233     * @return
234     */
235     public static String divideToString(BigDecimal dividend, BigDecimal divisor){
236       return formatToString(dividend.divide(divisor, MATHCONTEXT));
237     }
238 
239     /**
240     * <p>Description: 除法返回格式化结果字符串</p>
241     * @param dividend
242     * @param divisor
243     * @return
244     */
245     public static String divideToString(String dividend, String divisor){
246       BigDecimal decimalDividend = newBigDecimal(dividend);
247       BigDecimal decimalDivisor = newBigDecimal(divisor);
248       return formatToString(decimalDividend.divide(decimalDivisor, MATHCONTEXT));
249     }
250     /**
251     * <p>Description: 月利率计算</p>
252     * @param yearInterestRate
253     * @return
254     */
255     public static BigDecimal monthInterestRate(BigDecimal yearInterestRate){
256       BigDecimal dayInterestRate = MoneyUtils.divide(yearInterestRate, YEARDAYS).setScale(5, RoundingMode.CEILING);
257       System.err.println(dayInterestRate);
258       BigDecimal monthInterestRate = dayInterestRate.multiply(newBigDecimal(MOTHDAYS));
259       System.err.println(monthInterestRate);
260       return monthInterestRate;
261     }
262 
263     /**
264     * <p>Description: 按既定小数位数格式化金额保存</p>
265     * @param result
266     * @return
267     */
268     public static BigDecimal formatMoney(BigDecimal result){
269       return result.setScale(SCALE, SAVEROUNDINGMODE);
270     }
271 
272     /**
273     * <p>Description: 按既定小数位数格式化金额显示</p>
274     * @param resultStr 要格式化的数
275     * @param multiple 乘以的倍数
276     * @return
277     */
278     public static String formatMoneyToShow(String resultStr, BigDecimal multiple){
279       BigDecimal result = newBigDecimal(resultStr);
280       return MoneyUtils.formatToString(MoneyUtils.formatMoneyToShow(result, multiple));
281     }
282 
283     /**
284     * <p>Description: 按既定小数位数格式化金额显示</p>
285     * @param result 要格式化的数
286     * @param multiple 乘以的倍数
287     * @return
288     */
289     public static BigDecimal formatMoneyToShow(BigDecimal result, BigDecimal multiple){
290       return result.multiply(multiple).setScale(MONEYSHOWSCALE, SAVEROUNDINGMODE);
291     }
292 
293     /**
294     * <p>Description: 按既定小数位数格式化利率显示</p>
295     * @param result 要格式化的数
296     * @param multiple 乘以的倍数
297     * @return
298     */
299     public static BigDecimal formatInterestRateToShow(BigDecimal result, BigDecimal multiple){
300       return result.multiply(multiple).setScale(INTERESTRATESHOWSCALE, SAVEROUNDINGMODE);
301     }
302 
303     /**
304     * <p>Description: 按既定小数位数格式化显示</p>
305     * @param result 要格式化的数
306     * @param scale 显示标度(小数位数)
307     * @return
308     */
309     public static BigDecimal formatToShow(BigDecimal result, int scale){
310       return result.setScale(scale, SAVEROUNDINGMODE);
311     }
312 
313     /**
314     * <p>Description: 格式化为字符串,进行去零不去零操作</p>
315     * @param result
316     * @return
317     */
318     public static String formatToString(BigDecimal result){
319       if(result == null){
320         return "";
321       }else{
322         return STRIPTRAILINGZEROS ? result.stripTrailingZeros().toPlainString() : result.toPlainString();
323       }
324     }
325 
326     /**
327     * <p>Description: 按既定小数位数格式化为货币格式</p>
328     * @param result
329     * @return
330     */
331     public static String formatToCurrency(BigDecimal result){
332       BigDecimal temp = result.divide(HUNDRED, SAVEROUNDINGMODE);
333       NumberFormat numberFormat = NumberFormat.getCurrencyInstance();
334       return numberFormat.format(STRIPTRAILINGZEROS ? temp.stripTrailingZeros() : temp);
335     }
336 
337     public static String formatToPercent(BigDecimal result){
338       BigDecimal temp = result.divide(HUNDRED, SAVEROUNDINGMODE);
339       NumberFormat numberFormat = NumberFormat.getPercentInstance();
340       return numberFormat.format(STRIPTRAILINGZEROS ? temp.stripTrailingZeros() : temp);
341     }
342 
343     /** 
344     * <p>Description:格式化数字为千分位显示; </p>
345     * @param text 
346     * @return 
347     */ 
348     public static String fmtMicrometer(String text){ 
349       DecimalFormat df = null; 
350       if(text.indexOf(".") > 0) { 
351         if(text.length() - text.indexOf(".")-1 == 0){ 
352           df = new DecimalFormat("###,##0."); 
353         }else if(text.length() - text.indexOf(".")-1 == 1){ 
354           df = new DecimalFormat("###,##0.0"); 
355         }else { 
356           df = new DecimalFormat("###,##0.00"); 
357         } 
358       }else{ 
359         df = new DecimalFormat("###,##0.00"); 
360       } 
361       double number = 0.0; 
362       try { 
363         number = Double.parseDouble(text); 
364       } catch (Exception e) { 
365         number = 0.0; 
366       } 
367       return df.format(number); 
368     }
369 
370   }