MySQL中FLOAT、DOUBLE、DECIMAL运算结果不一致的原因是什么
MySQL不同数值类型运算结果差异原因说明
复现场景
建表语句
CREATE TABLE `testdb`.`typenumbers` ( `id` INT(11) NOT NULL AUTO_INCREMENT , `type_flo` FLOAT(10,10) NOT NULL , `type_dbl` DOUBLE(10,10) NOT NULL , `type_dec` DECIMAL(10,8) NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB;
插入数据语句
INSERT INTO `typenumbers` (`id`, `type_flo`, `type_dbl`, `type_dec`) VALUES (NULL, '1.2', '1.2', '1.2');
执行运算查询
SELECT (1.1 * `type_flo`) as flo, (1.1 * `type_dbl`) as dbl, (1.1 * `type_dec`) as deci FROM `typenumbers`;
返回结果
+--------------+--------------+-------------+ | flo | dbl | deci | +--------------+--------------+-------------+ | 1.3200000525 | 1.3200000000 | 1.320000000 | +--------------+--------------+-------------+
差异产生的核心原因
问题本质是三类数值类型的底层存储逻辑不同:
- FLOAT(单精度浮点数):32位二进制近似存储,无法精确表示所有十进制小数,1.1、1.2这类十进制小数转换为二进制浮点数时本身就存在精度损失,单精度的精度较低,运算后误差会放大到肉眼可见的程度,所以结果出现了1.3200000525的误差后缀。
- DOUBLE(双精度浮点数):64位二进制近似存储,同样是近似值类型,但精度远高于FLOAT,本次场景下运算产生的误差极小,在定义的(10,10)长度限制下无法显示出来,所以看起来结果是精确的,但多次累加或者数值范围更大时依然会出现精度误差。
- DECIMAL(定点数):采用十进制规则存储,属于精确值类型,只要数值在定义的长度范围内,存储和运算全程都不会产生精度损失,所以运算结果完全精确。
选型建议
- 对精度要求不高的科学计算、普通数值统计场景,可以使用FLOAT/DOUBLE,运算性能更高。
- 涉及金额、财务统计等对精度要求极高的业务场景,必须使用DECIMAL类型,避免精度误差导致的业务损失。
内容的提问来源于stack exchange,提问作者Şahin Ersever
相关产品推荐
相关产品推荐

