免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 28331 | 回复: 0

MySQL浮点计算存在的问题与解决方案 [复制链接]

论坛徽章:
2
数据库技术版块每日发帖之星
日期:2016-03-10 06:20:00数据库技术版块每日发帖之星
日期:2016-06-23 06:20:00
发表于 2016-06-20 15:47 |显示全部楼层

如有疑问请联系微信:onesoft007 

     在计算机中,浮点数往往很难精确表示,那么浮点数运算结果也往往难以精确表示。MySQL同样也存在这个问题,并表现在如下几个方面。

问题

1、相同的输入,可能造成不一样的输出(受CPU、编译器等影响) 

  a)下面是MySQL官方网站给出的例子

mysql> CREATE TABLE t1 (i INT, d1 DOUBLE, d2 DOUBLE);
mysql> INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
    -> (2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
    -> (2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
    -> (4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
    -> (5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
    -> (6, 0.00, 0.00), (6, -51.40, 0.00);

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b
    -> FROM t1 GROUP BY i HAVING a <> b;

+------+-------+------+
| i    | a     | b    |
+------+-------+------+
|    1 |  21.4 | 21.4 |
|    2 |  76.8 | 76.8 |
|    3 |   7.4 |  7.4 |
|    4 |  15.4 | 15.4 |
|    5 |   7.2 |  7.2 |
|    6 | -51.4 |    0 |
+------+-------+------+
  当i=1时,a=21.4、b=21.4,本不满足a<>b这个条件,可是MySQL仍然判定a与b不相等。

     b)在本地虚拟机测试时(Centos 6.4 X86_64)

+------+--------------------+------+
| i    | a                  | b    |
+------+--------------------+------+
|    1 | 21.400000000000006 | 21.4 |
|    2 |  76.80000000000001 | 76.8 |
|    3 |  7.399999999999999 |  7.4 |
|    4 | 15.399999999999999 | 15.4 |
|    5 |  7.199999999999999 |  7.2 |
|    6 |              -51.4 |    0 |
+------+--------------------+------+

2、结果受浮点数本身的精确度影响
  把double改成float,结果如下
+------+---------------------+--------------------+
| i    | a                   | b                  |
+------+---------------------+--------------------+
|    1 |  21.400001525878906 | 21.399999618530273 |
|    2 |   76.79999828338623 |  76.80000114440918 |
|    3 |   7.399999618530273 |  7.400000095367432 |
|    5 |   7.200000762939453 |  7.199999809265137 |
|    6 | -51.400001525878906 |                  0 |
+------+---------------------+--------------------+
解决方案
1、decimal
  在MySQL中,带有小数的精确运算可以使用decimal类型
  CREATE TABLE t3 (i INT, d1 decimal(10,3), d2 decimal(10,3));
  +------+---------+-------+
  | i    | a       | b     |
  +------+---------+-------+
  |    6 | -51.400 | 0.000 |
  +------+---------+-------+
限制
  decimal的精确表示为decimal(M,D),其中M最大为65,D最大为30。因此其表示的范围是远远小于double所能表示的范围

2、基于应用的解决方案
  比如商品价格涉及到小数,用20.95元表示,那么可以把价格变成以分为单位,即变成2095。

结论
  不要使用float、double以及其等价类型做精确计算。如果要在MySQL中做精确计算,推荐使用decimal或者将相关计算任务交给应用。
如有疑问请联系微信:onesoft007
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP