首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 浮點數比較陷阱:DOUBLE/FLOAT 不精確本質與 DECIMAL 解決方案

     編輯:MySQL 資料庫相關知識

核心觀念

  • FLOAT/DOUBLE:IEEE 754 二進位浮點數,無法精確表示許多十進位小數(如 0.1、21.4)。
  • DECIMAL:以字串儲存,精確度固定,適合金融、計量等嚴禁誤差場景。
  • MySQL 以 64 位十進位精度執行 DECIMAL 運算。

實測案例

CREATE TABLE t1 (i INT, d1 DOUBLE, d2 DOUBLE);
INSERT INTO t1 VALUES
(1, 101.40, 21.40), (1, -80.00, 0.00),
(2, 0.00, 0.00), (2, -13.20, 0.00),
(2, 59.60, 46.40), (2, 30.40, 30.40),
(3, 37.00, 7.40), (3, -29.60, 0.00),
(4, 60.00, 15.40), (4, -10.60, 0.00),
(4, -34.00, 0.00), (5, 33.00, 0.00),
(5, -25.80, 0.00), (5, 0.00, 7.20),
(6, 0.00, 0.00), (6, -51.40, 0.00);

SELECT i, SUM(d1) AS a, SUM(d2) AS b
FROM t1 GROUP BY i HAVING a <> b;

結果顯示 6 筆差異,其中前 5 組肉眼看數值相同,實際二進位表示已有微小誤差(約 1e-10 量級)。

改用 DECIMAL 後

同樣查詢僅回傳第 6 筆(真正數學不等),前 5 組消失,證明 DECIMAL 避免了浮點誤差。

最佳實踐建議

  1. 金額、精度敏感欄位:一律用 DECIMAL(precision, scale),如 DECIMAL(12,2)。
  2. 科學計算、近似值可接受:可用 DOUBLE,但比較時改用容差:
    WHERE ABS(d1 - d2) < 0.0001
  3. 避免直接 = 比較浮點欄位,無論是 WHERE、JOIN、GROUP BY。
  4. 應用層:語言端同樣存在浮點問題(Java BigDecimal、Python Decimal、JS 整分存儲),統一策略。

型別選擇速查表

型別儲存大小精確度適用場景
FLOAT4 bytes~7 位有效數字科學測量、圖形座標
DOUBLE8 bytes~15 位有效數字高精度科學計算
DECIMAL(M,D)M/2+2 bytes精確至 D 位小數金融、價格、庫存、比率
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved