在 MySQL 中,FLOAT
、DOUBLE
和 DECIMAL
是三种存储浮点数的数据类型,它们在 精度、存储方式和适用场景 上有显著区别。以下是详细对比和选择建议:
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
看起来一样,但实际上 FLOAT
和 DOUBLE
存储的是近似值。
方法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
- 可以看到
FLOAT
和DOUBLE
存储的0.1
并不精确,而DECIMAL
是精确的。 FLOAT
和DOUBLE
即使不计算,存储的仍然是近似值。
3. 如何选择?
✅ 使用 FLOAT
或 DOUBLE
的场景
- 科学计算(如温度、物理测量)。
- 对精度要求不高,但需要快速计算的场景。
- 存储非常大或非常小的数值(如天文数据)。
✅ 使用 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. 注意事项
- 比较操作:
DECIMAL
可直接用=
比较,而FLOAT/DOUBLE
应使用范围比较(如ABS(a - b) < 1e-9
)。 - 迁移兼容性:
DECIMAL
在其他数据库中可能叫NUMERIC
(两者在 MySQL 中完全等价)。 - 空间优化:
不要过度使用DECIMAL
,例如DECIMAL(20,2)
会占用更多空间,而实际可能只需DECIMAL(10,2)
。
评论