/*** 用于高精确处理常用的数学运算*/public class ArithmeticUtils {//默认除法运算精度private static final int DEF_DIV_SCALE = 10;/*** 提供精确的加法运算** @param v1 被加数* @param v2 加数* @return 两个参数的和*/public static double add(double v1, double v2) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.add(b2).doubleValue();}/*** 提供精确的加法运算** @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 加数* @param scale 保留scale 位小数* @return 两个参数的和*/public static String add(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供精确的减法运算** @param v1 被减数* @param v2 减数* @return 两个参数的差*/public static double sub(double v1, double v2) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.subtract(b2).doubleValue();}/*** 提供精确的减法运算。** @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 减数* @param scale 保留scale 位小数* @return 两个参数的差*/public static String sub(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供精确的乘法运算** @param v1 被乘数* @param v2 乘数* @return 两个参数的积*/public static double mul(double v1, double v2) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.multiply(b2).doubleValue();}/*** 提供精确的乘法运算** @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 保留scale 位小数* @return 两个参数的积*/public static double mul(double v1, double v2, int scale) {BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return round(b1.multiply(b2).doubleValue(), scale);}/*** 提供精确的乘法运算** @param v1 被乘数* @param v2 乘数* @param scale 保留scale 位小数* @return 两个参数的积*/public static String mul(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到* 小数点以后10位,以后的数字四舍五入** @param v1 被除数* @param v2 除数* @return 两个参数的商*/public static double div(double v1, double v2) {return div(v1, v2, DEF_DIV_SCALE);}/*** 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指* 定精度,以后的数字四舍五入** @param v1 被除数* @param v2 除数* @param scale 表示表示需要精确到小数点以后几位。* @return 两个参数的商*/public static double div(double v1, double v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(Double.toString(v1));BigDecimal b2 = new BigDecimal(Double.toString(v2));return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();}/*** 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指* 定精度,以后的数字四舍五入** @param v1 被除数* @param v2 除数* @param scale 表示需要精确到小数点以后几位* @return 两个参数的商*/public static String div(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v1);return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 提供精确的小数位四舍五入处理** @param v 需要四舍五入的数字* @param scale 小数点后保留几位* @return 四舍五入后的结果*/public static double round(double v, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b = new BigDecimal(Double.toString(v));return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();}/*** 提供精确的小数位四舍五入处理** @param v 需要四舍五入的数字* @param scale 小数点后保留几位* @return 四舍五入后的结果*/public static String round(String v, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b = new BigDecimal(v);return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 取余数** @param v1 被除数* @param v2 除数* @param scale 小数点后保留几位* @return 余数*/public static String remainder(String v1, String v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();}/*** 取余数 BigDecimal** @param v1 被除数* @param v2 除数* @param scale 小数点后保留几位* @return 余数*/public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {if (scale < 0) {throw new IllegalArgumentException("The scale must be a positive integer or zero");}return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);}/*** 比较大小** @param v1 被比较数* @param v2 比较数* @return 如果v1 大于v2 则 返回true 否则false*/public static boolean compare(String v1, String v2) {BigDecimal b1 = new BigDecimal(v1);BigDecimal b2 = new BigDecimal(v2);int bj = b1.compareTo(b2);boolean res;if (bj > 0)res = true;elseres = false;return res;}}
工具类2
import java.math.BigDecimal;import java.math.RoundingMode;import java.text.NumberFormat;/*** @Description:全局 BigDecimal 工具类* @Author: tarzan* @Date: 2021/09/31 9:06*/public class SmartBigDecimalUtil {/*** 价格类型 保留小数点 2*/public static final int PRICE_DECIMAL_POINT = 2;/*** 价格类型 保留小数点 6*/public static final int SIX_PRICE_DECIMAL_POINT = 6;/*** 重量类型保留小数点 3*/public static final int WEIGHT_DECIMAL_POINT = 3;/*** 金额相关计算方法:四舍五入 保留2位小数点*/public static class Amount {public static BigDecimal add(BigDecimal num1, BigDecimal num2) {return setScale(num1.add(num2), PRICE_DECIMAL_POINT);}public static BigDecimal multiply(BigDecimal num1, BigDecimal num2) {return setScale(num1.multiply(num2), PRICE_DECIMAL_POINT);}public static BigDecimal subtract(BigDecimal num1, BigDecimal num2) {return setScale(num1.subtract(num2), PRICE_DECIMAL_POINT);}public static BigDecimal divide(BigDecimal num1, BigDecimal num2) {return setScale(num1.divide(num2, RoundingMode.HALF_UP), PRICE_DECIMAL_POINT);}}/*** 金额相关计算方法:四舍五入 保留2位小数点*/public static class AmountSix {public static BigDecimal add(BigDecimal num1, BigDecimal num2) {return setScale(num1.add(num2), SIX_PRICE_DECIMAL_POINT);}public static BigDecimal multiply(BigDecimal num1, BigDecimal num2) {return setScale(num1.multiply(num2), SIX_PRICE_DECIMAL_POINT);}public static BigDecimal subtract(BigDecimal num1, BigDecimal num2) {return setScale(num1.subtract(num2), SIX_PRICE_DECIMAL_POINT);}public static BigDecimal divide(BigDecimal num1, BigDecimal num2) {return num1.divide(num2, PRICE_DECIMAL_POINT, RoundingMode.HALF_UP);}}/*** 重量相关计算方法:四舍五入 保留3位小数点*/public static class Weight {public static BigDecimal add(BigDecimal num1, BigDecimal num2) {return setScale(num1.add(num2), WEIGHT_DECIMAL_POINT);}public static BigDecimal multiply(BigDecimal num1, BigDecimal num2) {return setScale(num1.multiply(num2), WEIGHT_DECIMAL_POINT);}public static BigDecimal subtract(BigDecimal num1, BigDecimal num2) {return setScale(num1.subtract(num2), WEIGHT_DECIMAL_POINT);}public static BigDecimal divide(BigDecimal num1, BigDecimal num2) {return num1.divide(num2, WEIGHT_DECIMAL_POINT, RoundingMode.HALF_UP);}}/*** BigDecimal 加法 num1 + num2* 未做非空校验** @param num1* @param num2* @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT* @return BigDecimal*/public static BigDecimal add(BigDecimal num1, BigDecimal num2, int point) {return setScale(num1.add(num2), point);}/*** BigDecimal 乘法 num1 x num2* 未做非空校验** @param num1* @param num2* @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT* @return BigDecimal*/public static BigDecimal multiply(BigDecimal num1, BigDecimal num2, int point) {return setScale(num1.multiply(num2), point);}/*** BigDecimal 减法 num1 - num2* 未做非空校验** @param num1* @param num2* @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT* @return BigDecimal*/public static BigDecimal subtract(BigDecimal num1, BigDecimal num2, int point) {return setScale(num1.subtract(num2), point);}/*** BigDecimal 除法 num1/num2* 未做非空校验** @param num1* @param num2* @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT* @return BigDecimal*/public static BigDecimal divide(BigDecimal num1, BigDecimal num2, int point) {return num1.divide(num2, point, RoundingMode.HALF_UP);}/*** 设置小数点类型为 四舍五入** @param num* @param point* @return BigDecimal*/public static BigDecimal setScale(BigDecimal num, int point) {return num.setScale(point, RoundingMode.HALF_UP);}/*** 比较 num1 是否大于 num2** @param num1* @param num2* @return boolean*/public static boolean isGreaterThan(BigDecimal num1, BigDecimal num2) {return num1.compareTo(num2) == 1;}/*** 比较 num1 是否大于等于 num2** @param num1* @param num2* @return boolean*/public static boolean isGreaterOrEqual(BigDecimal num1, BigDecimal num2) {return isGreaterThan(num1, num2) || equals(num1, num2);}/*** 比较 num1 是否小于 num2** @param num1* @param num2* @return boolean*/public static boolean isLessThan(BigDecimal num1, BigDecimal num2) {return num1.compareTo(num2) == - 1;}/*** 比较 num1 是否小于等于 num2** @param num1* @param num2* @return boolean*/public static boolean isLessOrEqual(BigDecimal num1, BigDecimal num2) {return isLessThan(num1, num2) || equals(num1, num2);}/*** 比较 num1 是否等于 num2** @param num1* @param num2* @return*/public static boolean equals(BigDecimal num1, BigDecimal num2) {return num1.compareTo(num2) == 0;}/*** 计算 num1 / num2 的百分比** @param num1* @param num2* @return String*/public static String getPercentage(BigDecimal num1, BigDecimal num2) {BigDecimal result = num1.divide(num2, 4, RoundingMode.HALF_UP);NumberFormat percent = NumberFormat.getPercentInstance();percent.setMaximumFractionDigits(2);return percent.format(result.doubleValue());}/*** 计算 num1 / num2 的百分比** @param num1* @param num2* @param point 保留几位小数* @return String*/public static BigDecimal bigDecimalPercent(Integer num1, Integer num2, int point) {if (num1 == null || num2 == null) {return BigDecimal.ZERO;}if (num2.equals(Integer.valueOf(0))) {return BigDecimal.ZERO;}BigDecimal bigDecimalNum1 = new BigDecimal(num1);BigDecimal bigDecimalNum2 = new BigDecimal(num2);return bigDecimalPercent(bigDecimalNum1, bigDecimalNum2, point);}/*** 计算 num1 / num2 的百分比** @param num1* @param num2* @param point 保留几位小数* @return String*/public static BigDecimal bigDecimalPercent(BigDecimal num1, BigDecimal num2, int point) {if (num1 == null || num2 == null) {return BigDecimal.ZERO;}if (equals(BigDecimal.ZERO, num2)) {return BigDecimal.ZERO;}BigDecimal percent = num1.divide(num2, point + 2, RoundingMode.HALF_UP);BigDecimal percent100 = percent.multiply(new BigDecimal(100)).setScale(point);return percent100;}/*** 判断num是否为空 或者 零** @param num* @return String*/public static Boolean isEmpty(BigDecimal num) {return null == num || equals(BigDecimal.ZERO, num);}/*** 判断num是否 不等于null 并且不等于零** @param num* @return String*/public static Boolean isNotEmpty(BigDecimal num) {return ! isEmpty(num);}/*** 转换为万** @param num* @param point* @return*/public static BigDecimal convertTenThousand(BigDecimal num, int point) {BigDecimal decimal = num.divide(new BigDecimal(10000), point, RoundingMode.HALF_UP);return decimal;}/*** 转换为负数** @param num* @return*/public static BigDecimal convertToMinusNumber(BigDecimal num) {if (isLessOrEqual(num, BigDecimal.ZERO)) {return num;}return BigDecimal.ZERO.subtract(num);}}
工具类3
/*** @author wuke* @date 2022年03月22日 11:37*/public class BigDecimalUtil {/*** 对BigDecimal求2次平方根,精度无损失。*/public static BigDecimal sqrt(BigDecimal value) {BigDecimal val = BigDecimal.valueOf(Math.sqrt(value.doubleValue()));return val.add(BigDecimal.valueOf(value.subtract(val.multiply(val)).doubleValue() / (val.doubleValue() * 2.0)));}/*** 对BigDecimal求平方根,结果四舍五入** @param scale 几次方* @return java.math.BigDecimal* @author wuke* @date 2022/3/22 14:06*/public static BigDecimal sqrt(BigDecimal value, int scale) {if (value.compareTo(BigDecimal.ZERO) == 0) {return new BigDecimal(0);}BigDecimal num2 = BigDecimal.valueOf(2);int precision = 100;BigDecimal deviation = value;int cnt = 0;while (cnt < precision) {deviation = (deviation.add(value.divide(deviation, 100, RoundingMode.HALF_UP))).divide(num2, 100, RoundingMode.HALF_UP);cnt++;}deviation = deviation.setScale(scale, RoundingMode.HALF_UP);return deviation;}}
