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