Java中的簡單浮點數類型float和double不能夠進行運算,或者運算會丟失精度,不光是Java,在其它很多編程語言中也有這樣的問題。在大多數情況下,計算的結果是準確的,float和double只能用來做科學計算或者是工程計算,在商業計算中我們要用 java.math.BigDecimal
package com.xinzhi.util;
/**
* 引入BigDecimal工具類
*/
import com.sun.org.apache.regexp.internal.RE;
import com.xinzhi.constant.FinanceConstant;
import java.math.BigDecimal;
import java.text.DecimalFormat;
/**
* @author 空巷
* 金錢計算工具類
*/
public class ArithUtil {
//千位分隔符 方便查看金額具體大小
public static final String BIG_NUM_FMT_COMMA = "#,###,###,###,###,###,##0.00";
//不帶千位分隔符
public static final String BIG_NUM_FMT = "##################0.00";
//100常量
public static final String BIG_NUM_HUNDRED = "100";
//保留兩位小數
public static final int BIG_NUM_SCALE = 2;
//一年的還款利率 利率自定義 可更改
public static final double ONE_YEAR_INTEREST_RATE = 0.0531;
private ArithUtil(){}
/**
* 精確加法工具類
* @param v1 加數
* @param v2 被加數
* @return ;兩個參數的和
*/
public static BigDecimal add(String v1, String v2){
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2);
}
/**
* 精確減法運算
* @param v1 減數
* @param v2 被減數
* @return 兩個參數的差
*/
public static BigDecimal sub(String v1, String v2){
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.subtract(b2);
}
/**
* 精確乘法運算
* @param v1 乘數
* @param v2 被乘數
* @return 兩個參數的積
*/
public static BigDecimal mul(String v1, String v2){
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2);
}
/**
* 精確除法運算
* @param v1 除數
* @param v2 被除數
* @param scale 表示精確小數點後幾位
* @return 兩個參數的商
* @throws IllegalAccessException
*/
public static BigDecimal div(String v1, String v2, int scale){
if (scale < 0){
try {
throw new IllegalAccessException(
// 如果scale小於0,則拋出異常“比例必須是一個正整數或零”
"The scale must be a positive integer or zero");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP);
}
/**
* 保留小數位
* @param v
* @param scale
* @return
* @throws IllegalAccessException
*/
public static BigDecimal round(String v, int scale){
if (scale < 0){
try {
throw new IllegalAccessException(
// 如果scale小於0,則拋出異常“比例必須是一個正整數或零”
"The scale must be a positive integer or zero");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
BigDecimal b1 = new BigDecimal(v);
BigDecimal b2 = new BigDecimal("1");
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP);
}
/**
* 分轉換成元
* @param v
* @return
*/
public static BigDecimal penny2dollar(String v){
//保留兩位小數
BigDecimal s = ArithUtil.div(v,"100",2);
return s;
}
/**
* 元轉換成分
* @param v
* @return
*/
public static BigDecimal dollar2penny(String v){
return mul(v, "100");
}
/**
* 格式化金額
* 千位分隔符 方便查看金額具體大小 BIG_NUM_FMT = "#,###,###,###,###,###,##0.00"
* 精確兩位小數 .99 -> 0.99
* 1111111.985 -> 1,111,111.99
* @param v
* @return
*/
public static String formatNumber(String v){
return formatNumber(v, FinanceConstant.BIG_NUM_FMT_COMMA);
}
/**
* 格式化金額
* @param v
* @param pattern BigNum類中的常量 BIG_NUM_FMT_COMMA,BIG_NUM_FMT
* @return
*/
public static String formatNumber(String v,String pattern) {
return new DecimalFormat(pattern).format(new BigDecimal(v));
}
/**
* 一次還本付息法
* 計算到期一次還本付息金額
* 到期一次還本付息額=貸款本金×[1+年利率(%)] (貸款期爲一年)
* 到期一次還本付息額=貸款本金×[1+月利率(‰)×貸款期(月)] (貸款期不到一年)
* @param v1
* @return
*/
public static String singleUseRepayment(String v1,int month){
BigDecimal b1 = new BigDecimal(v1);
//當分期一年時的應償還金額
if (month == 12){
BigDecimal multiply = b1.multiply(BigDecimal.valueOf(1 + FinanceConstant.ONE_YEAR_INTEREST_RATE));
//保留兩位小數
BigDecimal round = ArithUtil.round(String.valueOf(multiply), 2);
//格式化金額
return ArithUtil.formatNumber(String.valueOf(round));
}else{
//計算月利率
BigDecimal b2 = new BigDecimal(1 + FinanceConstant.ONE_YEAR_INTEREST_RATE / 12 * month);
//保留兩位小數
BigDecimal round = ArithUtil.round(String.valueOf(b1.multiply(b2)), 2);
//格式化金額
return ArithUtil.formatNumber(String.valueOf(round));
}
}
//測試方法
public static void main(String[] args) {
// System.out.println(ArithUtil.add("1.99","20.999"));
// System.out.println(ArithUtil.sub("1.99","20.999"));
String s = "1111111.985";
String a = ArithUtil.formatNumber(s);
System.out.println(ArithUtil.singleUseRepayment("5000",11));
// System.out.println(s);
// System.out.println(a);
System.out.println(ArithUtil.round("5000.2343423",2));
}
}