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