1. 程式人生 > >常用貸款收益計算

常用貸款收益計算

package incomeCalculator;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;


public class IncomeCalculator {

private static final BigDecimal bg100 = new BigDecimal(100);
private static final BigDecimal bg360 = new BigDecimal(360);
private static final BigDecimal bg12 = new BigDecimal(12);
private static final BigDecimal bg3 = new BigDecimal(3);
private static final BigDecimal bg1 = new BigDecimal(1);
private static final BigDecimal bg0 = new BigDecimal(0);

private static final long dayOfMillisecond = 24 * 60 * 60 * 1000;

private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

public static final DecimalFormat df = new DecimalFormat("#,##,##0.00");
/**
* DEBX---等額本息---自然月---期限單位:月
YCFQ---本息到期一次性付清---自然月---期限單位:月||天
AJHB---每月付息,按季還本---自然月---期限單位:月
DEBJ---等額本金---自然月||固定日---期限單位:月
MYFX---每月付息,到期還本---自然月||固定日---期限單位:月
*/

public static void main(String[] args) throws IOException {
System.out.println("===========收益計算器===========");
System.out.println("=====請選擇以下型別");
System.out.println("1-1:[DEBX]---等額本息");
System.out.println("1-2:[YCFQ]---本息到期一次性付清");
System.out.println("1-3:[AJHB]---每月付息,按季還本");
System.out.println("1-4:[DEBJ]---等額本金");
System.out.println("1-5:[MYFX]---每月付息,到期還本");
System.out.println("=====請選擇以下付息方式");
System.out.println("2-1:[MON]---自然月");
System.out.println("2-2:[DAY]---固定日");
System.out.println("=====請選擇以下期限單位");
System.out.println("3-1:[QXMON]---月");
System.out.println("3-2:[QXDAY]---天");
System.out.println("輸入資料如(DEBX,MON,QXMON,1000,8.5,5)");
System.out.println("上面資料含義:等額本息,自然月,期限單位(月),投資金額1000元,年利率8.5%,期限5個月");

String jklx = null;
String fxfs = null;
String qxdw = null;
String tzje = null;
String nll = null;
String jkqx = null;
String inputStr = null;
while(true){
System.out.println("=====請輸入...........(輸入資料英文逗號分隔,輸入0退出)");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
inputStr = br.readLine();
String input[] = inputStr.split(",");
if("0".equals(input[0])){
System.exit(0);
}
jklx = input[0];
fxfs = input[1];
qxdw = input[2];
tzje = input[3];
nll = input[4];
jkqx = input[5];
BigDecimal investAmt = new BigDecimal(tzje);
BigDecimal yearRate = new BigDecimal(nll).divide(bg100);
int qx = Integer.parseInt(jkqx);
switch (jklx) {
case "DEBX":
calcDEBX(jklx,fxfs,qxdw,investAmt,yearRate,qx);
break;
case "YCFQ":
calcYCFQ(jklx,fxfs,qxdw,investAmt,yearRate,qx);
break;
case "AJHB":
calcAJHB(jklx,fxfs,qxdw,investAmt,yearRate,qx);
break;
case "DEBJ":
calcDEBJ(jklx,fxfs,qxdw,investAmt,yearRate,qx);
break;
case "MYFX":
calcMYFX(jklx,fxfs,qxdw,investAmt,yearRate,qx);
break;
default:
System.out.println("未識別的還款方式");
break;
}
}
}

/**
* 每月付息
* @param jklx 借款方式
* @param fxfs 付息方式
* @param qxdw 期限單位
* @param investAmt 投資金額
* @param yearRate  年利率
* @param qx 借款期限
*/
private static void calcMYFX(String jklx, String fxfs, String qxdw,
BigDecimal investAmt, BigDecimal yearRate,int qx) {
if("MON".equals(fxfs) && "QXMON".equals(qxdw)){
System.out.println("每月付息,自然月付息,收益計算開始...");
BigDecimal monthRate = yearRate.divide(bg12,9,BigDecimal.ROUND_HALF_UP);
System.out.println("月利率:"+monthRate);
Calendar calendar = Calendar.getInstance();
//還款日期
String repayDate = null;
//總收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//本金
BigDecimal bjOFmon = bg0;
for (int i = 1; i <= qx; i++) {
calendar.add(Calendar.MONTH, 1);
repayDate = sdf.format(calendar.getTime());
syOFmon = investAmt.multiply(monthRate).setScale(2, BigDecimal.ROUND_HALF_UP);
if(i == qx){
bjOFmon = investAmt;
}
sy = sy.add(syOFmon);
//金額判斷  金額小於0置為0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(syOFmon.compareTo(bg0) < 0){
syOFmon = bg0;
}
System.out.println("第"+i+"期|還款時間:"+repayDate+"|還款本金:"+df.format(bjOFmon)+"|還款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFmon)));
}
System.out.println("總收益:"+df.format(sy));
}else{
System.out.println("每月付息,固定日付息(預設15號),收益計算開始...");
Calendar calendar = Calendar.getInstance();
int today = calendar.get(Calendar.DAY_OF_MONTH);

Calendar endDate = Calendar.getInstance();
endDate.add(Calendar.MONTH, qx);
int lastDay = endDate.get(Calendar.DAY_OF_MONTH);
if(today == 15){
System.out.println("今天為15號,請參考自然月付息");
}else{
BigDecimal dayRate = yearRate.divide(bg360,9,BigDecimal.ROUND_HALF_UP);
System.out.println("日利率:"+dayRate);
//還款日期
String repayDate = null;
//總收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//本金
BigDecimal bjOFmon = bg0;

int fisrtDays = 0;
int lastDays = 0;

qx = qx +1 ;

for (int i = 1; i <= qx; i++) {
//第一期
if(i == 1){
if(today > 15){
// v1.0 存在bug,時間跨年,天數減出來為負數
// int start = calendar.get(Calendar.DAY_OF_YEAR);
// v2.0
long start = calendar.getTimeInMillis();
calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_MONTH, 15);
long end = calendar.getTimeInMillis();
fisrtDays = (int) ((end - start) / dayOfMillisecond);
}else{
long start = calendar.getTimeInMillis();
calendar.set(Calendar.DAY_OF_MONTH, 15);
long end = calendar.getTimeInMillis();
fisrtDays = (int) ((end - start) / dayOfMillisecond);
}
syOFmon = investAmt.multiply(dayRate).multiply(new BigDecimal(fisrtDays)).setScale(2, BigDecimal.ROUND_HALF_UP);
//最後一期
}else if(i == qx){
bjOFmon = investAmt;
if(lastDay > 15){
long start = calendar.getTimeInMillis();
long end = endDate.getTimeInMillis();
lastDays = (int) ((end - start) / dayOfMillisecond);
calendar = endDate;
}else{
long end = calendar.getTimeInMillis();
calendar.add(Calendar.MONTH, -1);
calendar.set(Calendar.DAY_OF_MONTH, 15);
long start = endDate.getTimeInMillis();
lastDays = (int) ((end - start) / dayOfMillisecond);
}
syOFmon = investAmt.multiply(dayRate).multiply(new BigDecimal(lastDays)).setScale(2, BigDecimal.ROUND_HALF_UP);
//中間期數
}else{
long start = calendar.getTimeInMillis();
calendar.add(Calendar.MONTH, 1);
long end = calendar.getTimeInMillis();
int days = (int) ((end - start) / dayOfMillisecond);
syOFmon = investAmt.multiply(dayRate)
.multiply(new BigDecimal(days)).setScale(2, BigDecimal.ROUND_HALF_UP);
}
sy = sy.add(syOFmon);
//金額判斷  金額小於0置為0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(syOFmon.compareTo(bg0) < 0){
syOFmon = bg0;
}
repayDate = sdf.format(calendar.getTime());
System.out.println("第"+i+"期|還款時間:"+repayDate+"|還款本金:"+df.format(bjOFmon)+"|還款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFmon)));
}
System.out.println("第一期:"+fisrtDays+"天|最後一期:"+lastDays+"天|其餘期數按月計息");
System.out.println("總收益:"+df.format(sy));
}
}
}


/**
* 等額本金
* @param jklx 借款方式
* @param fxfs 付息方式
* @param qxdw 期限單位
* @param investAmt 投資金額
* @param yearRate  年利率
* @param qx 借款期限
*/
private static void calcDEBJ(String jklx, String fxfs, String qxdw, 
BigDecimal investAmt, BigDecimal yearRate,int qx) {
if("MON".equals(fxfs) && "QXMON".equals(qxdw)){
System.out.println("等額本金,自然月付息,收益計算開始...");
BigDecimal monthRate = yearRate.divide(bg12,9,BigDecimal.ROUND_HALF_UP);
System.out.println("月利率:"+monthRate);
Calendar calendar = Calendar.getInstance();
//還款日期
String repayDate = null;
//總收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//每月平均本金
BigDecimal bjOFmon = investAmt.divide(new BigDecimal(qx),2,BigDecimal.ROUND_DOWN);
for (int i = 1; i <= qx; i++) {
calendar.add(Calendar.MONTH, 1);
repayDate = sdf.format(calendar.getTime());
syOFmon = investAmt.multiply(monthRate).setScale(2, BigDecimal.ROUND_HALF_UP);
if(i == qx){
bjOFmon = investAmt;
}
//本金減少
investAmt = investAmt.subtract(bjOFmon);
sy = sy.add(syOFmon);
//金額判斷  金額小於0置為0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(syOFmon.compareTo(bg0) < 0){
syOFmon = bg0;
}
System.out.println("第"+i+"期|還款時間:"+repayDate+"|還款本金:"+df.format(bjOFmon)+"|還款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFmon)));
}
System.out.println("總收益:"+df.format(sy));
}else if("DAY".equals(fxfs) && "QXMON".equals(qxdw)){
System.out.println("等額本金,固定日(預設15號),收益計算開始...");
BigDecimal monthRate = yearRate.divide(bg12,9,BigDecimal.ROUND_HALF_UP);
System.out.println("月利率:"+monthRate);
BigDecimal dayRate = yearRate.divide(bg360,9,BigDecimal.ROUND_HALF_UP);
System.out.println("日利率:"+dayRate);

Calendar calendar = Calendar.getInstance();
int today = calendar.get(Calendar.DAY_OF_MONTH);

Calendar endDate = Calendar.getInstance();
endDate.add(Calendar.MONTH, qx);
int lastDay = endDate.get(Calendar.DAY_OF_MONTH);
//還款日期
String repayDate = null;
//總收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//月本金
BigDecimal bjOFmon = bg0;
//月平均本金
BigDecimal ypjbjOFmon = investAmt.divide(new BigDecimal(qx),2,BigDecimal.ROUND_HALF_UP);

//首期天數
int fisrtDays = 0;
//尾期天數
int lastDays = 0;
if(lastDay > 15){
long end = endDate.getTimeInMillis();
endDate.set(Calendar.DAY_OF_MONTH, 15);
long start = endDate.getTimeInMillis();
endDate.set(Calendar.DAY_OF_MONTH, today);
lastDays = (int) ((end - start) / dayOfMillisecond);
}else{
lastDays = lastDay;
}

if(today > 15){
long start = calendar.getTimeInMillis();
calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_MONTH, 15);
long end = calendar.getTimeInMillis();
fisrtDays = (int) ((end - start) / dayOfMillisecond);
}else{
long start = calendar.getTimeInMillis();
calendar.set(Calendar.DAY_OF_MONTH, 15);
long end = calendar.getTimeInMillis();
fisrtDays = (int) ((end - start) / dayOfMillisecond);
}

//首期與尾期為一個月,則本金按實際天數計算佔比
BigDecimal fisOFALL = new BigDecimal(fisrtDays)
.divide(new BigDecimal(fisrtDays)
.add(new BigDecimal(lastDays)),
5,BigDecimal.ROUND_HALF_UP);

qx = qx +1 ;

for (int i = 1; i <= qx; i++) {
//第一期
if(i == 1){
syOFmon = investAmt.multiply(dayRate).multiply(new BigDecimal(fisrtDays)).setScale(2, BigDecimal.ROUND_HALF_UP);
bjOFmon = ypjbjOFmon.multiply(fisOFALL).setScale(2, BigDecimal.ROUND_DOWN);
//最後一期
}else if(i == qx){
syOFmon = investAmt.multiply(dayRate).multiply(new BigDecimal(lastDays)).setScale(2, BigDecimal.ROUND_HALF_UP);
calendar = endDate;
bjOFmon = investAmt;
//中間期數
}else{
bjOFmon = ypjbjOFmon;
syOFmon = investAmt.multiply(monthRate).setScale(2, BigDecimal.ROUND_HALF_UP);
calendar.add(Calendar.MONTH, 1);
}
sy = sy.add(syOFmon);
investAmt = investAmt.subtract(bjOFmon);
//金額判斷  金額小於0置為0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(syOFmon.compareTo(bg0) < 0){
syOFmon = bg0;
}
repayDate = sdf.format(calendar.getTime());
System.out.println("第"+i+"期|還款時間:"+repayDate+"|還款本金:"+df.format(bjOFmon)+"|還款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFmon)));
}
System.out.println("第一期:"+fisrtDays+"天|最後一期:"+lastDays+"天|第一期天數/(第一期天數+最後一期天數):"+fisOFALL+"|其餘期數按月計息");
System.out.println("總收益:"+df.format(sy));
}else{
System.out.println("等額本金,不支援借款期限為天");
}
}


/**
* 按季還本
* @param jklx 借款方式
* @param fxfs 付息方式
* @param qxdw 期限單位
* @param investAmt 投資金額
* @param yearRate  年利率
* @param qx 借款期限
*/
private static void calcAJHB(String jklx, String fxfs, String qxdw, 
BigDecimal investAmt, BigDecimal yearRate,int qx) {
if("MON".equals(fxfs) && "QXMON".equals(qxdw)){
System.out.println("按季還本,自然月付息,收益計算開始...");
BigDecimal monthRate = yearRate.divide(bg12,9,BigDecimal.ROUND_HALF_UP);
System.out.println("月利率:"+monthRate);
Calendar calendar = Calendar.getInstance();
//還款日期
String repayDate = null;
//總收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//每月平均本金
BigDecimal bjOFmon = investAmt.divide(new BigDecimal(qx),2,BigDecimal.ROUND_HALF_UP);
for (int i = 1; i <= qx; i++) {
calendar.add(Calendar.MONTH, 1);
repayDate = sdf.format(calendar.getTime());
//季本金
BigDecimal bjOFquarter = bg0;
syOFmon = investAmt.multiply(monthRate).setScale(2, BigDecimal.ROUND_HALF_UP);
//最後一期
if(i == qx){
bjOFquarter = investAmt;
}else{
//減少本金
if(i % 3 == 0){
bjOFquarter = bjOFmon.multiply(bg3);
investAmt = investAmt.subtract(bjOFquarter);
}
}

//金額判斷  金額小於0置為0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(bjOFquarter.compareTo(bg0) < 0){
bjOFquarter = bg0;
}
sy = sy.add(syOFmon);
System.out.println("第"+i+"期|還款時間:"+repayDate+"|還款本金:"+df.format(bjOFquarter)+"|還款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFquarter)));
}
System.out.println("總收益:"+df.format(sy));
}else{
System.out.println("按季還本,不支援固定日方式還款,不支援借款期限為天");
}
}


/**
* 一次付清 
* @param jklx 借款方式
* @param fxfs 付息方式
* @param qxdw 期限單位
* @param investAmt 投資金額
* @param yearRate  年利率
* @param qx 借款期限
*/
private static void calcYCFQ(String jklx, String fxfs, String qxdw, 
BigDecimal investAmt, BigDecimal yearRate,int qx) {
//累積利息
BigDecimal sy = bg0;
System.out.println("一次付清 ,收益計算開始...");
Calendar calendar = Calendar.getInstance();
//按月
if("QXMON".equals(qxdw)){
calendar.add(Calendar.MONTH, qx);
//利息 = 投資金額 * 專案年利率 *借款期限 / 12 (保留兩位小數)
sy = investAmt.multiply(yearRate)
  .multiply(new BigDecimal(qx))
     .divide(bg12, 2, BigDecimal.ROUND_HALF_UP);
//按天
}else{
calendar.add(Calendar.DAY_OF_YEAR, qx);
//利息 = 投資金額 * 專案年利率 *借款期限 / 360 (保留兩位小數)
sy = investAmt.multiply(yearRate)
 .multiply(new BigDecimal(qx))
 .divide(bg360, 2, BigDecimal.ROUND_HALF_UP);
}
System.out.println("還款時間:"+sdf.format(calendar.getTime())+"|還款本金:"+df.format(investAmt)+"|還款利息:"+df.format(sy)+"|本息和:"+df.format(investAmt.add(sy)));
}


/**
* 等額本息計算
* @param jklx 借款方式
* @param fxfs 付息方式
* @param qxdw 期限單位
* @param investAmt 投資金額
* @param yearRate  年利率
* @param qx 借款期限
*/
private static void calcDEBX(String jklx, String fxfs, String qxdw, 
BigDecimal investAmt, BigDecimal yearRate,int qx) {
if("MON".equals(fxfs) && "QXMON".equals(qxdw)){
System.out.println("等額本息,自然月付息,收益計算開始...");
BigDecimal monthRate = yearRate.divide(bg12,9,BigDecimal.ROUND_HALF_UP);
System.out.println("月利率:"+monthRate);
BigDecimal tmp = monthRate.add(bg1).pow(qx);
BigDecimal monthPayTotal = investAmt.multiply(monthRate).multiply(tmp).divide(tmp.subtract(new BigDecimal(1)), 2,BigDecimal.ROUND_DOWN);
System.out.println("每月應付本息:"+monthPayTotal);
Calendar calendar = Calendar.getInstance();
//還款日期
String repayDate = null;
//總收益
BigDecimal sy = bg0;
//月收益
BigDecimal syOFmon = bg0;
//月本金
BigDecimal bjOFmon = bg0;
for (int i = 1; i <= qx; i++) {
calendar.add(Calendar.MONTH, 1);
repayDate = sdf.format(calendar.getTime());
//最後一期
if(i == qx){
bjOFmon = investAmt;
syOFmon = monthPayTotal.subtract(investAmt);
}else{
syOFmon = investAmt.multiply(monthRate).setScale(2, BigDecimal.ROUND_HALF_UP);
bjOFmon = monthPayTotal.subtract(syOFmon);
//減少本金
investAmt = investAmt.subtract(bjOFmon);
}

//金額判斷  金額小於0置為0
if(bjOFmon.compareTo(bg0) < 0){
bjOFmon = bg0;
}
if(syOFmon.compareTo(bg0) < 0){
syOFmon = bg0;
}
sy = sy.add(syOFmon);
System.out.println("第"+i+"期|還款時間:"+repayDate+"|還款本金:"+df.format(bjOFmon)+"|還款利息:"+df.format(syOFmon)+"|本息和:"+df.format(syOFmon.add(bjOFmon)));
}
System.out.println("總收益:"+df.format(sy));
}else{
System.out.println("等額本息,不支援固定日方式還款,不支援借款期限為天");
}
}

/*public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, 2017);
calendar.set(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_YEAR, 31);
System.out.println(sdf.format(calendar.getTime()));
calendar.add(Calendar.MONTH, 1);
System.out.println(sdf.format(calendar.getTime()));
}*/
}