package com.xxx.common.utils;
import java.math.BigDecimal;
import java.text.NumberFormat;
/**
* 四则运算
*
* @author lt
* @version 2018年11月10日上午9:15:02
*/
public class CalcUtil {
/**
* 保留小数位
*/
private static final int DEF_DIV_SCALE = 4;
/**
* 结果值
*/
private BigDecimal currNum = null;
private CalcUtil(BigDecimal decimal) {
currNum = decimal;
}
/**
* 判断一个数字是否是decimal,不是的话,转换包装
*
* @param v1
* @return
*/
private static BigDecimal covertToDecimal(Number v1) {
BigDecimal value;
if (v1 instanceof BigDecimal) {
value = (BigDecimal) v1;
} else {
value = new BigDecimal(v1.toString());
}
return value;
}
/**
* 初始化运算对象
*
* @param v1
* @return
*/
public static CalcUtil init(Number v1) {
return new CalcUtil(covertToDecimal(v1));
}
/**
* 直接相加
*
* @return
*/
public static CalcUtil addDirect(Number... v2) {
BigDecimal value = BigDecimal.ZERO;
for (Number number : v2) {
value = value.add(covertToDecimal(number));
}
return new CalcUtil(value);
}
/**
* 运算结果后,跟着相加
*
* @param v1
* @return
*/
public CalcUtil add(Number... v1) {
for (Number number : v1) {
this.currNum = this.currNum.add(covertToDecimal(number));
}
return this;
}
/**
* 两数直接相减
*
* @param v2 被减数
* @return
*/
public static CalcUtil subDirect(Number... v2) {
BigDecimal value = BigDecimal.ZERO;
for (Number number : v2) {
value = value.subtract(covertToDecimal(number));
}
return new CalcUtil(value);
}
/**
* 运算结果后,跟着相减
*
* @param v1 减数
* @return
*/
public CalcUtil sub(Number... v1) {
for (Number number : v1) {
this.currNum = this.currNum.subtract(covertToDecimal(number));
}
return this;
}
/**
* 两数直接相乘
*
* @param v2
* @return
*/
public static CalcUtil mulDirect(Number... v2) {
BigDecimal value = BigDecimal.ZERO;
for (Number number : v2) {
value = value.multiply(covertToDecimal(number));
}
return new CalcUtil(value);
}
/**
* 运算结果后,跟着相乘
*
* @param v1
* @return
*/
public CalcUtil mul(Number... v1) {
for (Number number : v1) {
this.currNum = this.currNum.multiply(covertToDecimal(number));
}
return this;
}
/**
* 两数直接相除
*
* @param v2 被除数
* @return
*/
public static CalcUtil divDirect(Number... v2) {
BigDecimal value = BigDecimal.ZERO;
for (Number number : v2) {
// 此处保留20位,减少误差
value = value.divide(covertToDecimal(number), 20, BigDecimal.ROUND_HALF_UP);
}
return new CalcUtil(value);
}
/**
* 运算结果后,跟着相除
*
* @param v1 除数
* @return
*/
public CalcUtil div(Number... v1) {
for (Number number : v1) {
// 此处保留20位,减少误差
this.currNum = this.currNum.divide(covertToDecimal(number), 20, BigDecimal.ROUND_HALF_UP);
}
return this;
}
/**
* 返回结果,可不传参数
*
* @param scale 保留位数,默认2位小数
* @return
*/
public float floatValue(int... scale) {
if (scale.length > 0) {
return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP).floatValue();
}
return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).floatValue();
}
/**
* 返回结果,可不传参数
*
* @param scale 保留位数,默认2位小数
* @return
*/
public long longValue(int... scale) {
if (scale.length > 0) {
return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP).longValue();
}
return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).longValue();
}
/**
* 返回结果,可不传参数
*
* @param scale 保留位数,默认2位小数
* @return
*/
public int intValue(int... scale) {
if (scale.length > 0) {
return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP).intValue();
}
return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).intValue();
}
/**
* 返回结果,可不传参数
*
* @param scale 保留位数,默认2位小数
* @return
*/
public double doubleValue(int... scale) {
if (scale.length > 0) {
return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP).doubleValue();
}
return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 返回结果,可不传参数
*
* @param scale 保留位数,默认2位小数
* @return
*/
public short shortValue(int... scale) {
if (scale.length > 0) {
return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP).shortValue();
}
return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).shortValue();
}
/**
* 返回结果,可不传参数
*
* @param scale 保留位数,默认2位小数
* @return
*/
public BigDecimal decimalValue(int... scale) {
if (scale.length > 0) {
return currNum.setScale(scale[0], BigDecimal.ROUND_HALF_UP);
}
return currNum.setScale(DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP);
}
/**
* 返回字符串值
*
* @param thousands 是否千分符
* @param scale 保留几位小数
* @return
*/
public String stringValue(boolean thousands, int... scale) {
BigDecimal bigDecimal = decimalValue(scale);
NumberFormat numberFormat = NumberFormat.getInstance();
if (scale.length > 0) {
numberFormat.setMinimumFractionDigits(scale[0]);
} else {
numberFormat.setMinimumFractionDigits(DEF_DIV_SCALE);
}
numberFormat.setGroupingUsed(thousands);
return numberFormat.format(bigDecimal);
}
}
使用方式如下
// 0原生计算
System.out.println("原生:" + (0.1 + 0.2));
// 1.链式操作
double v1 = CalcUtils.init(0).add(0.1).add(0.2).doubleValue();
System.out.println("链式:" + v1);
// 2.直接操作
double v2 = CalcUtils.add(0.1, 0.2).doubleValue();
System.out.println("直接:" + v2);
// 3.混合运算,支持任何类型
float v3 = CalcUtils.add(0.3, 0.5f).mul(0.5d).div(2L).sub(2).add((short) 2).floatValue();
System.out.println("混合运算:" + v3);
// 4.小数位默认2位
double v4 = CalcUtils.div(2, 3).doubleValue();
System.out.println("小数默认2位:" + v4);
// 5.小数位可调整调整
double v5 = CalcUtils.div(2, 3).doubleValue(6);
System.out.println("调整小数位:" + v5);
结果
原生: 0.30000000000000004
链式: 0.3
直接: 0.3
混合运算: 0.2
小数默认2位: 0.67
调整小数位: 0.666667