package com.ruoyi.common.utils; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Arrays; import java.util.Collection; import java.util.Optional; /** * @author yuan * @date 2026-04-23 13:10 * @description BigDecimal工具类 */ public class BigDecimalUtils { public static BigDecimal getBigDecimalValue(BigDecimal val) { return Optional.ofNullable(val).orElse(BigDecimal.ZERO); } public static BigDecimal of(Object val) { if (val == null) { return null; } try { if (val instanceof Double || val instanceof Float) { return BigDecimal.valueOf(((Number) val).doubleValue()); } if (val instanceof Number) { return new BigDecimal(val.toString()); } return new BigDecimal(val.toString().trim()); } catch (NumberFormatException e) { throw new IllegalArgumentException("无法转换 " + val + " 为 BigDecimal类型 ", e); } } /** * 安全转换方法,将对象转为BigDecimal,null视为0 * @param number 可以是Number、String或BigDecimal * @return 对应的BigDecimal,null转为0 */ public static BigDecimal safe(Object number) { if (number == null) return BigDecimal.ZERO; if (number instanceof BigDecimal) return (BigDecimal) number; if (number instanceof Number) return BigDecimal.valueOf(((Number) number).doubleValue()); try { return new BigDecimal(number.toString()); } catch (NumberFormatException e) { return BigDecimal.ZERO; } } /** * 加法运算(自动处理null值) * @param values 多个加数 * @return 和 */ public static BigDecimal add(Object... values) { return Arrays.stream(values) .map(BigDecimalUtils::safe) .reduce(BigDecimal.ZERO, BigDecimal::add); } /** * 减法运算(自动处理null值) * @param minuend 被减数 * @param subtrahends 减数 * @return 差 */ public static BigDecimal subtract(Object minuend, Object... subtrahends) { BigDecimal result = safe(minuend); for (Object subtrahend : subtrahends) { result = result.subtract(safe(subtrahend)); } return result; } /** * 乘法运算(自动处理null值,任何参数为null则返回0) * @param values 多个乘数 * @return 积 */ public static BigDecimal multiply(Object... values) { if (values == null || values.length == 0) { return BigDecimal.ZERO; } BigDecimal result = Arrays.stream(values) .map(BigDecimalUtils::safe) .reduce(BigDecimal.ONE, BigDecimal::multiply); // 标准化结果:如果是0,去除所有小数位;否则保留原有小数位 return stripTrailingZeros(result); } /** * 除法运算(自动处理null值) * @param dividend 被除数 * @param divisor 除数 * @param scale 小数位数 * @param roundingMode 舍入模式 * @return 商 */ public static BigDecimal divide(Object dividend, Object divisor, int scale, RoundingMode roundingMode) { BigDecimal d1 = safe(dividend); BigDecimal d2 = safe(divisor); if (d2.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } return stripTrailingZeros(d1.divide(d2, scale, roundingMode)); } /** * 除法运算(自动处理null值) * @param dividend 被除数 * @param divisor 除数 * @param scale 小数位数 * @param roundingMode 舍入模式 * @return 商 */ public static BigDecimal dividePercentage(Object dividend, Object divisor, int scale, RoundingMode roundingMode) { BigDecimal d1 = safe(dividend); BigDecimal d2 = safe(divisor); if (d2.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } BigDecimal multiplied = d1.multiply(new BigDecimal("100")); BigDecimal result = multiplied.divide(d2, scale, roundingMode); return stripTrailingZeros(result); } /** * 比较两个数的大小(自动处理null值,null视为0) * @param num1 第一个数 * @param num2 第二个数 * @return 1: num1 > num2; 0: num1 = num2; -1: num1 < num2 */ public static int compare(Object num1, Object num2) { return safe(num1).compareTo(safe(num2)); } /** * 四舍五入(自动处理null值) * @param value 原始值 * @param scale 保留小数位数 * @return 四舍五入后的值 */ public static BigDecimal round(Object value, int scale) { return safe(value).setScale(scale, RoundingMode.HALF_UP); } /** * 求和(流式处理版) * @param numbers 数字集合 * @return 和 */ public static BigDecimal sum(Collection numbers) { return numbers.stream() .map(BigDecimalUtils::safe) .reduce(BigDecimal.ZERO, BigDecimal::add); } /** * 标准化BigDecimal结果 * 1. 如果是0,去除所有小数位 * 2. 如果不是0,去除末尾无意义的0 */ public static BigDecimal stripTrailingZeros(BigDecimal value) { if (value.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } return new BigDecimal(value.stripTrailingZeros().toPlainString()); } }