refactor(util): 重构KitBigDecimalUtil类提高精度控制和数据类型支持

This commit is contained in:
2026-01-30 19:02:50 +08:00
parent c828e27b95
commit ae1de44b2c
2 changed files with 101 additions and 68 deletions
@@ -16,6 +16,7 @@
package cn.odboy.util; package cn.odboy.util;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.text.NumberFormat; import java.text.NumberFormat;
@@ -33,17 +34,21 @@ public final class KitBigDecimalUtil {
* @return 转换后的 BigDecimal * @return 转换后的 BigDecimal
*/ */
private static BigDecimal toBigDecimal(Object obj) { private static BigDecimal toBigDecimal(Object obj) {
if (obj instanceof BigDecimal) { return switch (obj) {
return (BigDecimal) obj; case BigDecimal result -> result;
} else if (obj instanceof Long) { case Long result -> BigDecimal.valueOf(result);
return BigDecimal.valueOf((Long) obj); case Integer result -> BigDecimal.valueOf(result.longValue());
} else if (obj instanceof Integer) { case Short result -> BigDecimal.valueOf(result.longValue());
return BigDecimal.valueOf((Integer) obj); case Byte result -> BigDecimal.valueOf(result.longValue());
} else if (obj instanceof Double) { case Double result -> BigDecimal.valueOf(result);
return new BigDecimal(String.valueOf(obj)); case Float result -> BigDecimal.valueOf(result.doubleValue());
} else { case String result -> new BigDecimal(result);
throw new IllegalArgumentException("Unsupported type"); case Number result -> BigDecimal.valueOf(result.doubleValue());
case null, default -> {
assert obj != null;
throw new IllegalArgumentException("Unsupported type: " + obj.getClass().getName());
} }
};
} }
/** /**
@@ -51,12 +56,12 @@ public final class KitBigDecimalUtil {
* *
* @param a 加数 * @param a 加数
* @param b 加数 * @param b 加数
* @return 两个加数的和, 保留两位小数 * @return 两个加数的和,
*/ */
public static BigDecimal add(Object a, Object b) { public static BigDecimal add(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a); BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b); BigDecimal bdB = toBigDecimal(b);
return bdA.add(bdB).setScale(2, RoundingMode.HALF_UP); return bdA.add(bdB);
} }
/** /**
@@ -64,12 +69,12 @@ public final class KitBigDecimalUtil {
* *
* @param a 被减数 * @param a 被减数
* @param b 减数 * @param b 减数
* @return 两数的差, 保留两位小数 * @return 两数的差,
*/ */
public static BigDecimal subtract(Object a, Object b) { public static BigDecimal subtract(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a); BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b); BigDecimal bdB = toBigDecimal(b);
return bdA.subtract(bdB).setScale(2, RoundingMode.HALF_UP); return bdA.subtract(bdB);
} }
/** /**
@@ -82,7 +87,7 @@ public final class KitBigDecimalUtil {
public static BigDecimal multiply(Object a, Object b) { public static BigDecimal multiply(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a); BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b); BigDecimal bdB = toBigDecimal(b);
return bdA.multiply(bdB).setScale(6, RoundingMode.HALF_UP); return bdA.multiply(bdB);
} }
/** /**
@@ -90,37 +95,23 @@ public final class KitBigDecimalUtil {
* *
* @param a 被除数 * @param a 被除数
* @param b 除数 * @param b 除数
* @return 两数的商,保留两位小数 * @return 两数的商
*/ */
public static BigDecimal divide(Object a, Object b) { public static BigDecimal divide(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a); BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b); BigDecimal bdB = toBigDecimal(b);
return bdA.divide(bdB, 6, RoundingMode.HALF_UP); return bdA.divide(bdB, 6, RoundingMode.DOWN);
}
/**
* 除法
*
* @param a 被除数
* @param b 除数
* @param scale 保留小数位数
* @return 两数的商,保留两位小数
*/
public static BigDecimal divide(Object a, Object b, int scale) {
BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b);
return bdA.divide(bdB, scale, RoundingMode.HALF_UP);
} }
/** /**
* 分转元 * 分转元
* *
* @param obj 分的金额 * @param obj 分的金额
* @return 转换后的元,保留两位小数 * @return 转换后的元
*/ */
public static BigDecimal centsToYuan(Object obj) { public static BigDecimal centsToYuan(Object obj) {
BigDecimal cents = toBigDecimal(obj); BigDecimal cents = toBigDecimal(obj);
return cents.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP); return cents.divide(BigDecimal.valueOf(100), 6, RoundingMode.DOWN);
} }
/** /**
@@ -129,9 +120,29 @@ public final class KitBigDecimalUtil {
* @param obj 元的金额 * @param obj 元的金额
* @return 转换后的分 * @return 转换后的分
*/ */
public static Long yuanToCents(Object obj) { public static long yuanToCents(Object obj) {
BigDecimal yuan = toBigDecimal(obj); BigDecimal yuan = toBigDecimal(obj);
return yuan.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP).longValue(); return yuan.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_EVEN).longValue();
}
/**
* 取整,采用银行家算法
*
* @param obj 金额
* @return /
*/
public static BigDecimal toRound(Object obj) {
return toBigDecimal(obj).setScale(0, RoundingMode.HALF_EVEN);
}
/**
* 取整,采用银行家算法
*
* @param obj 金额
* @return /
*/
public static long toRoundLong(Object obj) {
return toBigDecimal(obj).setScale(0, RoundingMode.HALF_EVEN).longValue();
} }
/** /**
@@ -162,5 +173,11 @@ public final class KitBigDecimalUtil {
System.out.println("分转元结果: " + centsToYuan(cents)); System.out.println("分转元结果: " + centsToYuan(cents));
BigDecimal yuan = new BigDecimal("123.45"); BigDecimal yuan = new BigDecimal("123.45");
System.out.println("元转分结果: " + yuanToCents(yuan)); System.out.println("元转分结果: " + yuanToCents(yuan));
BigDecimal toRo = new BigDecimal("123.1548456");
System.out.println("取整: " + toRound(toRo));
BigDecimal toRoLong = new BigDecimal("123.1548456");
System.out.println("取整转long: " + toRoundLong(toRoLong));
BigDecimal formatGa = new BigDecimal("1231548456123123");
System.out.println("格式化千分位: " + formatGroupingAmount(formatGa));
} }
} }
@@ -18,6 +18,7 @@ package cn.odboy.util;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.text.NumberFormat; import java.text.NumberFormat;
import lombok.experimental.UtilityClass; import lombok.experimental.UtilityClass;
/** /**
@@ -35,14 +36,17 @@ public final class KitBigDecimalUtil {
private static BigDecimal toBigDecimal(Object obj) { private static BigDecimal toBigDecimal(Object obj) {
if (obj instanceof BigDecimal) { if (obj instanceof BigDecimal) {
return (BigDecimal) obj; return (BigDecimal) obj;
} else if (obj instanceof Long) { } else if (obj instanceof Long || obj instanceof Integer ||
return BigDecimal.valueOf((Long) obj); obj instanceof Short || obj instanceof Byte) {
} else if (obj instanceof Integer) { return BigDecimal.valueOf(((Number) obj).longValue());
return BigDecimal.valueOf((Integer) obj); } else if (obj instanceof Double || obj instanceof Float) {
} else if (obj instanceof Double) { return BigDecimal.valueOf(((Number) obj).doubleValue());
return new BigDecimal(String.valueOf(obj)); } else if (obj instanceof String) {
return new BigDecimal((String) obj);
} else if (obj instanceof Number) {
return BigDecimal.valueOf(((Number) obj).doubleValue());
} else { } else {
throw new IllegalArgumentException("Unsupported type"); throw new IllegalArgumentException("Unsupported type: " + obj.getClass().getName());
} }
} }
@@ -51,12 +55,12 @@ public final class KitBigDecimalUtil {
* *
* @param a 加数 * @param a 加数
* @param b 加数 * @param b 加数
* @return 两个加数的和, 保留两位小数 * @return 两个加数的和,
*/ */
public static BigDecimal add(Object a, Object b) { public static BigDecimal add(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a); BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b); BigDecimal bdB = toBigDecimal(b);
return bdA.add(bdB).setScale(2, RoundingMode.HALF_UP); return bdA.add(bdB);
} }
/** /**
@@ -64,12 +68,12 @@ public final class KitBigDecimalUtil {
* *
* @param a 被减数 * @param a 被减数
* @param b 减数 * @param b 减数
* @return 两数的差, 保留两位小数 * @return 两数的差,
*/ */
public static BigDecimal subtract(Object a, Object b) { public static BigDecimal subtract(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a); BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b); BigDecimal bdB = toBigDecimal(b);
return bdA.subtract(bdB).setScale(2, RoundingMode.HALF_UP); return bdA.subtract(bdB);
} }
/** /**
@@ -82,7 +86,7 @@ public final class KitBigDecimalUtil {
public static BigDecimal multiply(Object a, Object b) { public static BigDecimal multiply(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a); BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b); BigDecimal bdB = toBigDecimal(b);
return bdA.multiply(bdB).setScale(6, RoundingMode.HALF_UP); return bdA.multiply(bdB);
} }
/** /**
@@ -90,37 +94,23 @@ public final class KitBigDecimalUtil {
* *
* @param a 被除数 * @param a 被除数
* @param b 除数 * @param b 除数
* @return 两数的商,保留两位小数 * @return 两数的商
*/ */
public static BigDecimal divide(Object a, Object b) { public static BigDecimal divide(Object a, Object b) {
BigDecimal bdA = toBigDecimal(a); BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b); BigDecimal bdB = toBigDecimal(b);
return bdA.divide(bdB, 6, RoundingMode.HALF_UP); return bdA.divide(bdB, 6, RoundingMode.DOWN);
}
/**
* 除法
*
* @param a 被除数
* @param b 除数
* @param scale 保留小数位数
* @return 两数的商,保留两位小数
*/
public static BigDecimal divide(Object a, Object b, int scale) {
BigDecimal bdA = toBigDecimal(a);
BigDecimal bdB = toBigDecimal(b);
return bdA.divide(bdB, scale, RoundingMode.HALF_UP);
} }
/** /**
* 分转元 * 分转元
* *
* @param obj 分的金额 * @param obj 分的金额
* @return 转换后的元,保留两位小数 * @return 转换后的元
*/ */
public static BigDecimal centsToYuan(Object obj) { public static BigDecimal centsToYuan(Object obj) {
BigDecimal cents = toBigDecimal(obj); BigDecimal cents = toBigDecimal(obj);
return cents.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP); return cents.divide(BigDecimal.valueOf(100), 6, RoundingMode.DOWN);
} }
/** /**
@@ -129,9 +119,29 @@ public final class KitBigDecimalUtil {
* @param obj 元的金额 * @param obj 元的金额
* @return 转换后的分 * @return 转换后的分
*/ */
public static Long yuanToCents(Object obj) { public static long yuanToCents(Object obj) {
BigDecimal yuan = toBigDecimal(obj); BigDecimal yuan = toBigDecimal(obj);
return yuan.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP).longValue(); return yuan.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_EVEN).longValue();
}
/**
* 取整,采用银行家算法
*
* @param obj 金额
* @return /
*/
public static BigDecimal toRound(Object obj) {
return toBigDecimal(obj).setScale(0, RoundingMode.HALF_EVEN);
}
/**
* 取整,采用银行家算法
*
* @param obj 金额
* @return /
*/
public static long toRoundLong(Object obj) {
return toBigDecimal(obj).setScale(0, RoundingMode.HALF_EVEN).longValue();
} }
/** /**
@@ -162,5 +172,11 @@ public final class KitBigDecimalUtil {
System.out.println("分转元结果: " + centsToYuan(cents)); System.out.println("分转元结果: " + centsToYuan(cents));
BigDecimal yuan = new BigDecimal("123.45"); BigDecimal yuan = new BigDecimal("123.45");
System.out.println("元转分结果: " + yuanToCents(yuan)); System.out.println("元转分结果: " + yuanToCents(yuan));
BigDecimal toRo = new BigDecimal("123.1548456");
System.out.println("取整: " + toRound(toRo));
BigDecimal toRoLong = new BigDecimal("123.1548456");
System.out.println("取整转long: " + toRoundLong(toRoLong));
BigDecimal formatGa = new BigDecimal("1231548456123123");
System.out.println("格式化千分位: " + formatGroupingAmount(formatGa));
} }
} }