| 特性 | FLOAT / DOUBLE | DECIMAL / NUMERIC |
|---|---|---|
| 儲存方式 | 二進制浮點數(IEEE 754) | 定點數,以字串形式逐位儲存 |
| 精度 | 近似值,有捨入誤差 | 精確值,無捨入誤差 |
| 適用場景 | 科學計算、測量數據、圖形座標 | 貨幣、金融、庫存計量、精確比對 |
| 空間 | FLOAT 4B、DOUBLE 8B | DECIMAL(M,D) 約 M+2 字節 |
| 比較運算 | 避免 = / <>,用範圍比較 | 可直接用 = / <> / BETWEEN |
CREATE TABLE t1 (c1 FLOAT(10,2), c3 DECIMAL(10,2));
INSERT INTO t1 VALUES (1234567.23, 1234567.23), (9876543.21, 9876543.12);
SELECT * FROM t1;
+------------+------------+
| c1 | c3 |
+------------+------------+
| 1234567.25 | 1234567.23 | -- FLOAT 產生誤差
| 9876543.00 | 9876543.12 | -- FLOAT 精度丟失
+------------+------------+
FLOAT(10,2) 非標準語法(M=總位數,D=小數位),實際精度受硬體影響。DECIMAL 精確保留輸入值。
INSERT INTO t1 VALUES (-98765430.21, -98765430.12);
SELECT * FROM t1;
+--------------+--------------+
| c1 | c3 |
+--------------+--------------+
| -98765432.00 | -98765430.12 | -- FLOAT 再次失真
+--------------+--------------+
符號位不佔精度位,但浮點誤差依然存在。
DECIMAL(65,30) 最大精度 65 位,標度 30 位。WHERE float_col = 1.23,改用 WHERE float_col BETWEEN 1.229 AND 1.231 或改欄位為 DECIMAL。BigDecimal、Python 用 decimal.Decimal、Go 用 shopspring/decimal,嚴禁 float64 運算金額。MySQL decimal_t 結構體以 decimal_digit_t 陣列(基數 10000)儲存,intg/frac 分別記錄整數/小數位數,sign 標記正負,運算皆為十進制模擬,故無二進制轉換誤差。