1. 為什么需要
DECIMAL
在數據庫中,常見的數值類型有:
INT
、BIGINT
→ 整數,存儲容量有限。
FLOAT
、DOUBLE
→ 浮點數,存儲效率高,但存在精度丟失問題。
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 中,浮點數(
float
、double
)也有精度問題,典型例子: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. 典型應用場景
金額字段
price DECIMAL(10,2) -- 最大 99999999.99
Java 中用
BigDecimal
接收,避免丟失精度。財務統計
統計總金額 → 必須保證無誤差
結算、報表 → 精確小數位
電商優惠計算
折扣、積分兌換、滿減 → 都需要
BigDecimal
來精確計算。
6. 總結
FLOAT
/DOUBLE
→ 高性能但有精度問題,適合科學計算、近似值場景。
DECIMAL
→ 精確存儲,適合金額和財務場景,性能稍低但可以接受。在 Java 中:
金額類 → 使用
BigDecimal
存入數據庫 → 使用
DECIMAL(M, D)
避免直接用
double
運算金額。