MySQL 浮點數與定點數精度陷阱:為什麼金額必須用 DECIMAL
直觀案例
CREATE TABLE test (c1 FLOAT(10,2), c2 DECIMAL(10,2));
INSERT INTO test VALUES (131072.32, 131072.32), (999998.02, 999998.02);
SELECT * FROM test;
+-----------+-----------+
| c1 | c2 |
+-----------+-----------+
| 131072.31 | 131072.32 | -- 浮點數丟失精度
| 999998.00 | 999998.02 | -- 浮點數丟失精度
+-----------+-----------+
核心差異
| 類型 | 分類 | 優點 | 缺點 |
| FLOAT / DOUBLE | 浮點數 | 定長下表示範圍極大 | 精度丟失,不可用於精確計算 |
| DECIMAL / NUMERIC | 定點數 | 精確存儲,適合貨幣 | 存儲空間稍大,範圍較小 |
工程落地四原則
- 浮點數存在誤差,嚴禁用於金額、價格、庫存等精度敏感場景;
- 此類業務強制使用 DECIMAL;
- 代碼中涉及浮點運算時,採用「整數分/厘存儲、展示再除」或專用庫(如 Java BigDecimal)規避比較陷阱;
- 注意浮點數特殊值(NaN、Infinity)處理。