在 MySQL 中,FLOATDOUBLEDECIMAL 是三种存储浮点数的数据类型,它们在 精度、存储方式和适用场景 上有显著区别。以下是详细对比和选择建议:


1. 核心区别对比

特性 FLOAT DOUBLE DECIMAL (NUMERIC)
存储方式 单精度浮点数(4字节) 双精度浮点数(8字节) 字符串形式存储的精确小数
精度 约 7 位有效数字 约 15 位有效数字 精确小数(可自定义精度)
计算方式 二进制近似计算 二进制近似计算 十进制精确计算
存储范围 ±1.18E-38 到 ±3.40E+38 ±2.23E-308 到 ±1.79E+308 依赖定义的精度和小数位数
是否精确 ❌ 可能有舍入误差 ❌ 可能有舍入误差 ✅ 完全精确
适用场景 科学计算、非精确数据 高精度科学计算 财务、货币等精确计算

2. 详细说明

(1) FLOAT

  • 特点

    • 单精度浮点数,计算速度快,占用空间小。
    • 存在二进制舍入误差(例如 0.1 + 0.2 ≠ 0.3)。
  • 示例

    CREATE TABLE example (price FLOAT);
    INSERT INTO example VALUES (123.456789); -- 实际可能存储为 123.45679
    

(2) DOUBLE

  • 特点

    • 双精度浮点数,精度比 FLOAT 更高,但仍有舍入误差。
    • 适用于需要更高精度的科学计算。
  • 示例

    CREATE TABLE example (distance DOUBLE);
    INSERT INTO example VALUES (123456.78901234567); -- 存储为 123456.789012345
    

(3) DECIMAL

  • 特点

    • DECIMAL字符串形式 存储数字,直接记录十进制每一位,不依赖二进制浮点表示。例如:DECIMAL(10,2) 存储 123.45 时,实际保存为字符序列 '1','2','3','.','4','5',无精度损失。
    • 需指定精度和小数位数(如 DECIMAL(10,2) 表示总共 10 位,其中 2 位小数)。
  • 示例

    CREATE TABLE example (salary DECIMAL(10,2));
    INSERT INTO example VALUES (12345.67); -- 精确存储为 12345.67
    

为什么float和double存储0.1,显示的仍是0.1,不计算是不是就是精确的?验证一下

方法1:直接查询存储的精确值
-- 创建一个表存储 FLOAT 和 DOUBLE
CREATE TABLE float_test (
    f FLOAT,
    d DOUBLE,
    dec DECIMAL(10,1)  -- 对比用
);

-- 插入 0.1
INSERT INTO float_test VALUES (0.1, 0.1, 0.1);

-- 查询存储的值
SELECT f, d, dec FROM float_test;

输出(可能):

f       | d                          | dec
--------|----------------------------|-----
0.1     | 0.1                        | 0.1

看起来一样,但实际上 FLOATDOUBLE 存储的是近似值。

方法2:用 CAST 查看真实存储
SELECT 
    CAST(f AS DECIMAL(30,25)) AS true_float_value,
    CAST(d AS DECIMAL(30,25)) AS true_double_value,
    dec
FROM float_test;

输出(示例):

true_float_value          | true_double_value                     | dec
--------------------------|--------------------------------------|-----
0.1000000014901161000000000 | 0.1000000000000000100000000000       | 0.1
  • 可以看到 FLOATDOUBLE 存储的 0.1不精确,而 DECIMAL 是精确的。
  • FLOATDOUBLE 即使不计算,存储的仍然是近似值

3. 如何选择?

✅ 使用 FLOATDOUBLE 的场景

  • 科学计算(如温度、物理测量)。
  • 对精度要求不高,但需要快速计算的场景。
  • 存储非常大或非常小的数值(如天文数据)。

✅ 使用 DECIMAL 的场景

  • 财务数据(如金额、汇率)。
  • 需要完全避免舍入误差的精确计算(如库存数量)。
  • 法律或审计要求的场景(如银行交易)。

❌ 避免使用 FLOAT/DOUBLE 的情况

  • 货币计算(可能导致 0.01 分误差)。
  • 需要等值比较的场景(如 WHERE price = 10.5 可能失败)。

4. 性能与存储权衡

类型 存储空间 计算速度 精度
FLOAT 小 (4B) 最快
DOUBLE 中 (8B)
DECIMAL 最慢

5. 实际示例

场景:电商平台

-- 商品价格(需精确到分)
CREATE TABLE products (
    id INT,
    price DECIMAL(10, 2)  -- 推荐:避免金额误差
);

-- 用户行为数据(如点击率,允许近似值)
CREATE TABLE user_metrics (
    user_id INT,
    click_rate FLOAT  -- 可接受误差
);

6. 注意事项

  1. 比较操作
    DECIMAL 可直接用 = 比较,而 FLOAT/DOUBLE 应使用范围比较(如 ABS(a - b) < 1e-9)。
  2. 迁移兼容性
    DECIMAL 在其他数据库中可能叫 NUMERIC(两者在 MySQL 中完全等价)。
  3. 空间优化
    不要过度使用 DECIMAL,例如 DECIMAL(20,2) 会占用更多空间,而实际可能只需 DECIMAL(10,2)