千家信息网

Double类型精度问题引起的错误

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,场景说明研发同事让把某个double类型字段的值四舍五入保留2位小数,mysql中round(col,2)可以实现四舍五入并且保留2位小数,但是神奇的事情发生了:发现有的四舍五入是正确的,而有的不是我
千家信息网最后更新 2026年11月01日Double类型精度问题引起的错误

场景说明

研发同事让把某个double类型字段的值四舍五入保留2位小数,mysql中round(col,2)可以实现四舍五入并且保留2位小数,但是神奇的事情发生了:发现有的四舍五入是正确的,而有的不是我们想要的结果,如下:简单模拟此场景:

yujx>drop table dd;
yujx>
create table dd (a double);
yujx>
insert into dd values(956.745),(231.34243252),(321.43534),(5464.446);
yujx>
select a,round(a,2) from dd;
+--------------+------------+
| a | round(a,2) |
+--------------+------------+
| 956.745 | 956.74 | #可以看到并不是我们期望的956.75
| 231.34243252 | 231.34 |
| 321.43534 | 321.44 |
| 5464.446 | 5464.45 |
+--------------+------------+
4 rows in set (0.00 sec)

如上,有的是正确的,有的不是我们期望的值,那么问题来了,为什么呢?

通过询问和网上搜索后,发现可能是因为double的精度问题导致的

查阅MySQL官当关于double、Float、DECIMAL, NUMERIC类型的介绍,如下:

FLOAT, DOUBLE

#为了说明问题,摘了官当的部分内容,关于更详细的介绍请直接查看官当。

12.2.3 Floating-Point Types (Approximate Value) - FLOAT, DOUBLE

#可以看到标题已经指出 Float和double是近似值

The FLOAT and DOUBLE types represent approximate numeric data values. MySQL uses four bytes for single-precision values and eight bytes for double-precision values.

Because floating-point values are approximate and not stored as exact values, attempts to treat them as exact in comparisons may lead to problems. They are also subject to platform or implementation dependencies. For more information, seeSection B.5.5.8, "Problems with Floating-Point Values

因为Float、Double存储的是一个近似值而不是确切的值,试图使用它们存储一个确切的值可以会导致问题。它们依赖于不同平台和不同实现方式,而官当在章节Section B.5.5.8, "Problems with Floating-Point Values中举例说明了此问题

参考:http://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html

"Problems with Floating-Point Values"

B.5.4.8 Problems with Floating-Point Values

Floating-point numbers sometimes cause confusion because they are approximate and not stored as exact values. A floating-point value as written in an SQL statement may not be the same as the value represented internally. Attempts to treat floating-point values as exact in comparisons may lead to problems. They are also subject to platform or implementation dependencies. The FLOAT and DOUBLE data types are subject to these issues. For DECIMALcolumns, MySQL performs operations with a precision of 65 decimal digits, which should solve most common inaccuracy problems.

由于浮点数存储的是近似值而不是确切的值,某些时候可能导致混乱。一个浮点数值在SQL语句作为内部表示的值可能不同。试图使用float、double来存储确切的值可能会出现问题,他们也依赖不同平台和实现方式。而对应DECIMAL类型,MySQL作为65位精度进行操作,可以解决此类精度问题。

如下例子证明使用Double运算遇到的异常错误

此结果是错误的,尽管前5条的a和b的值看起来是不满足a<>b条件的。

此现象取决于各种因素,如计算机架构、编译器版本或者优化级别等。例如,不同的CPU评估的浮点数不同。

如果将字段d1和d2改成DECIMAL类型,将不会存在此问题。如下:

综上,如果想精确的存储浮点数值,应该使用DECIMAL.比如金额等。

DECIMAL, NUMERIC

11.2.2 Fixed-Point Types (Exact Value) - DECIMAL, NUMERIC

The DECIMAL and NUMERIC types store exact numeric data values. These types are used when it

is important to preserve exact precision, for example with monetary data. In MySQL, NUMERIC is

implemented as DECIMAL。

DECIMAL和NUMBERIC存储的是确切的数值,使用它们可以保证精确度,例如用于存储金额数据。在MySQL中,NUMBERIC和DECIMAL以同样的类型实现。

double在其他平台

double类型不只是在MySQL中存在精度错误的问题,在oracle、Java等平台同样存在此问题,如下:

简单的0.2+0.4,但是返回的结果不是0.6。

回到问题开始

如果换成DECIMAL类型,round的结果将是正确的,如下:

yujx>drop table dd;
yujx>
create table dd (a double,b decimal(30,10));
yujx>
insert into dd

values(956.745,956.745),(231.34243252,231.34243252),(321.43534,321.43534),

(5464.446,5464.446);
yujx>
select a,round(a,2) from dd;

综上

只为说明一个问题,如果想要确切的存储小数(例如,金额等),建议使用DECIMAL类型,而不是DOUBLE、float类型。

参考:

http://dev.mysql.com/doc/refman/5.7/en/fixed-point-types.html

http://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html

http://dev.mysql.com/doc/refman/5.7/en/problems-with-float.html

http://justjavac.com/codepuzzle/2012/11/11/codepuzzle-float-who-stole-your-accuracy.html

问题 类型 存储 不同 精度 平台 结果 错误 四舍五入 小数 数值 近似值 金额 四舍 精确 场景 字段 方式 浮点 点数 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 华服互联网科技靠谱吗 科技互联网企业 科技和互联网公司 互联网科技卖菜 关于新基建和互联网科技 科技服务与互联网 苏州互联网科技贷款公司 佩信高科技互联网 科技与互联网的利与弊 贵州叶脉互联网科技有限公司所属行业 互联网科技有哪些公司 中国航天科技大学国际工业互联网 新兴科技互联网创新大赛颁奖典礼 滨湖区互联网智能科技产品有哪些 互联网科技快讯热点 扫呗互联网科技有限公司 广东鹅鹅鹅互联网科技有限公司 北京互联网科技类企业分布 三亚科技创新互联网基地 六子台科技互联网展会 智能科技公司是互联网公司吗 互联网的科技创新 互联网金融科技创新 互联网科技上市公司 融贸通互联网科技 栖莱科技互联网股份有限公司 互联网科技产业特征 西安小鹰速贷互联网科技有限公司 广州梦谷互联网科技有限公司领导 平安好医生打造互联网科技医疗
0