2026-05-11 6d5ce70c3e2b536c8e4b74269be70029a57cb1cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
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());
    }
}