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));
}
}