package com.vincent.rsf.server.common.utils;
|
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
|
/**
|
* 数量运算工具:使用 BigDecimal 避免 Double 精度问题。
|
* 实体仍为 Double 时,运算用本工具再转回 Double(保留 6 位小数)。
|
*/
|
public final class QuantityUtils {
|
|
private static final int SCALE = 6;
|
private static final RoundingMode ROUNDING = RoundingMode.HALF_UP;
|
|
private QuantityUtils() {
|
}
|
|
private static BigDecimal toBigDecimal(Double v) {
|
if (v == null) {
|
return BigDecimal.ZERO;
|
}
|
return BigDecimal.valueOf(v);
|
}
|
|
/**
|
* 加法:a + b,结果保留 6 位小数转 Double
|
*/
|
public static Double add(Double a, Double b) {
|
return toBigDecimal(a).add(toBigDecimal(b)).setScale(SCALE, ROUNDING).doubleValue();
|
}
|
|
/**
|
* 减法:a - b,结果保留 6 位小数转 Double
|
*/
|
public static Double subtract(Double a, Double b) {
|
return toBigDecimal(a).subtract(toBigDecimal(b)).setScale(SCALE, ROUNDING).doubleValue();
|
}
|
|
/**
|
* 比较:a 与 b 大小,避免直接用 Double 比较。
|
* 返回 a.compareTo(b):负/0/正
|
*/
|
public static int compare(Double a, Double b) {
|
return toBigDecimal(a).compareTo(toBigDecimal(b));
|
}
|
|
/**
|
* a > 0
|
*/
|
public static boolean isPositive(Double a) {
|
return compare(a, 0.0) > 0;
|
}
|
|
/**
|
* a >= 0
|
*/
|
public static boolean isNonNegative(Double a) {
|
return compare(a, 0.0) >= 0;
|
}
|
|
/**
|
* a <= 0
|
*/
|
public static boolean isNonPositive(Double a) {
|
return compare(a, 0.0) <= 0;
|
}
|
|
/**
|
* 乘法:a * b,结果保留 6 位小数转 Double
|
*/
|
public static Double multiply(Double a, Double b) {
|
return toBigDecimal(a).multiply(toBigDecimal(b)).setScale(SCALE, ROUNDING).doubleValue();
|
}
|
|
/**
|
* 除法:a / b,结果保留 6 位小数转 Double(b=0 时返回 0)
|
*/
|
public static Double divide(Double a, Double b) {
|
if (b == null || toBigDecimal(b).compareTo(BigDecimal.ZERO) == 0) {
|
return 0.0;
|
}
|
return toBigDecimal(a).divide(toBigDecimal(b), SCALE, ROUNDING).doubleValue();
|
}
|
|
/**
|
* 统一舍入到 6 位小数后转 Double(用于存库/展示、入参校验,避免浮点尾差)。
|
* 所有 Double 写入实体或参与比较前建议经此方法或 add/subtract 做精度控制。
|
*/
|
public static Double roundToScale(Double v) {
|
if (v == null) {
|
return 0.0;
|
}
|
return toBigDecimal(v).setScale(SCALE, ROUNDING).doubleValue();
|
}
|
}
|