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

MySQL FLOAT 型別精度陷阱與最佳實踐:IEEE 754 深度解析

     編輯:MySQL 資料庫相關知識

浮點數精度問題並非 MySQL 獨有,而是 IEEE 754 標準 導致的必然結果。單精度 FLOAT(32 位:1 符號位 + 8 指數位 + 23 尾數位)有效十進制數字約 **7-8 位**,超出即產生誤差;雙精度 DOUBLE(64 位)約 **15-16 位**。

核心現象演示

案例一:看似簡單的數值無法精確儲存

CREATE TABLE t (num FLOAT(9,3));
INSERT INTO t VALUES (123456.8);
SELECT * FROM t;  -- 顯示 123456.797(非 123456.800)

原因:123456.8 二進制尾數超過 23 位,捨入導致誤差。

案例二:條件查詢匹配失效

INSERT INTO t VALUES (2.8);
SELECT * FROM t WHERE num = 2.8;  -- 無結果!
-- 實際儲存值為 2.8000000715... 需用範圍查詢
SELECT * FROM t WHERE num BETWEEN 2.799 AND 2.801;

MySQL 數值型別對照

分類型別儲存精度適用場景
IEEE 754 浮點數FLOAT4 bytes~7 位科學計算、非精確測量
DOUBLE / REAL8 bytes~15 位較大範圍非精確計算
定點數(精確)DECIMAL / NUMERIC可變自定精確度貨幣、金融、庫存、精確測量

程式語言同樣受影響

// Java 範例
System.out.println(7.22f - 7.0f);  // 輸出 0.21999979 而非 0.22

浮點數比較嚴禁使用 ==/!=,應用 Math.abs(a-b) < epsilon 容差比較。

MySQL 5.0+ 實戰規避方案

  1. 首選 DECIMAL(p,s):貨幣、價格、數量等精敏欄位
  2. 若必須用 FLOAT:明確指定精度 FLOAT(10,2),查詢用 FORMAT(col,2) = FORMAT(val,2)(精度 ≤ 6)
  3. 避免在 WHERE 直接比較浮點欄位,改用範圍 BETWEEN 或整數化存儲(如分為單位存 INT)

總結鐵律

  1. 浮點數天生有誤差,金融/貨幣絕對禁用 FLOAT/DOUBLE
  2. 定點數 DECIMAL 是精確計算唯一正解
  3. 程式碼中杜絕浮點數直接比較,建立通用比較工具類
  4. 留意 NaN、Infinity、+0/-0 等特殊值處理
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved