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
