MySQL--MySQL中的DECIMAL 与 Java中的BigDecimal

发布于:2025-08-29 ⋅ 阅读:(18) ⋅ 点赞:(0)

1. 为什么需要 DECIMAL

在数据库中,常见的数值类型有:

  • INTBIGINT → 整数,存储容量有限。

  • FLOATDOUBLE → 浮点数,存储效率高,但存在精度丢失问题

  • DECIMAL(M, D) → 定点数,存储精确值

例子:

SELECT 0.1 + 0.2;   -- 结果可能是 0.30000000000000004

这是浮点数的经典精度问题。
如果用 DECIMAL(10,2) 存储:

INSERT INTO test (amount) VALUES (0.1), (0.2);
SELECT SUM(amount);  -- 结果就是 0.30 (精确)

👉 结论:金融、电商、会计等涉及金额的业务必须使用 DECIMAL,而不能用 FLOAT / DOUBLE


2. DECIMAL 的存储方式

  • DECIMAL(M, D) 表示总共 M 位数字,其中 D 位小数

    • M 最大 65(总位数)

    • D 最大 30(小数位数)

  • 存储为字符串形式的二进制编码,避免二进制浮点数误差。

  • 计算时精度高,但性能略低于 FLOAT / DOUBLE

例子:

DECIMAL(10,2)  -- 最大值:99999999.99
DECIMAL(18,6)  -- 最大值:999999999999.999999

3. MySQL 中 DECIMAL 与 Java 的对应关系

在 Java 中,浮点数(floatdouble)也有精度问题,典型例子:

System.out.println(0.1 + 0.2);  // 输出 0.30000000000000004

Java 中对应的精确数值类型是 BigDecimal

类型映射

MySQL 类型 Java JDBC 映射类型
DECIMAL / NUMERIC java.math.BigDecimal
FLOAT / DOUBLE Double / Float
INT / BIGINT Integer / Long

4. Java BigDecimal 使用注意事项

(1) 创建方式

BigDecimal a = new BigDecimal("0.1");   // 推荐,精确
BigDecimal b = new BigDecimal("0.2");
System.out.println(a.add(b));  // 0.3

// 不推荐
BigDecimal c = new BigDecimal(0.1); // 会有精度问题
System.out.println(c);  // 0.10000000000000000555...

(2) 常见操作

BigDecimal x = new BigDecimal("10.25");
BigDecimal y = new BigDecimal("2.5");

System.out.println(x.add(y));      // 加法
System.out.println(x.subtract(y)); // 减法
System.out.println(x.multiply(y)); // 乘法
System.out.println(x.divide(y, 2, RoundingMode.HALF_UP)); // 除法,保留2位四舍五入

(3) 比较大小

不能用 equals,需要用 compareTo

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("1.00");

System.out.println(a.equals(b));      // false(因为精度不同)
System.out.println(a.compareTo(b));   // 0(数值相等)

5. 典型应用场景

  1. 金额字段

    price DECIMAL(10,2)  -- 最大 99999999.99
    

    Java 中用 BigDecimal 接收,避免丢失精度。

  2. 财务统计

    • 统计总金额 → 必须保证无误差

    • 结算、报表 → 精确小数位

  3. 电商优惠计算

    • 折扣、积分兑换、满减 → 都需要 BigDecimal 来精确计算。


6. 总结

  • FLOAT / DOUBLE → 高性能但有精度问题,适合科学计算、近似值场景。

  • DECIMAL → 精确存储,适合金额和财务场景,性能稍低但可以接受。

  • 在 Java 中:

    • 金额类 → 使用 BigDecimal

    • 存入数据库 → 使用 DECIMAL(M, D)

    • 避免直接用 double 运算金额。