• 为什么MySQL的浮点数类型不够精准?(实例证明)


    1. /*******************************
    2. *FileName: 为什么MySQL的浮点数类型不够精准?
    3. *Author: weibo
    4. *Version: v1.0
    5. *Date: 2016.5.15
    6. *Description: 为什么MySQL的浮点数类型不够精准?
    7. **********************************/

    MySQL浮点数类型不精准,因此,在一些对精确度要求较高的项目中,不要使用浮点数。为什么不精确呢?下面通过一个简单的实例来分析。

    1、创建一个表,指定price字段为DOUBLE浮点数类型

    1. CREATE TABLE demo.goodsmaster
    2. (
    3. barcode TEXT,
    4. goodsname TEXT,
    5. price DOUBLE,
    6. itemnumber INT PRIMARY KEY AUTO_INCREMENT
    7. );

    2、插入两条数据

    1. INSERT INTO demo.goodsmaster( barcode, goodsname, price)VALUES ( '0001', '书', 0.57);
    2. INSERT INTO demo.goodsmaster( barcode, goodsname, price)VALUES ( '0002', '笔', 0.46);
    3. INSERT INTO demo.goodsmaster( barcode, goodsname, price)VALUES ( '0003', '笔', 0.27);

    3、查看数据,并把两个商品价格相加

    1. SELECT * from demo.goodsmaster;
    2. SELECT SUM(price) FROM demo.goodsmaster;

    期待值:0.57+0.46+0.27=1.1

    实际结果为:1.0999999999999999'

     当我们需要以通过数值对比为条件进行查询,一旦出现误差,就查不出需要的结果了:

    SELECT goodsname,SUM(price) FROM demo.goodsmaster GROUP BY goodsname having SUM(price)=1.1;

     4、为什么会出现这种情况?

    我们分析下MySQL对浮点类型数据的存储方式。FLOAT(4字节)和DOUBLE(8字节)都采用二进制的方式来进行存储数据,比如 9.625,用二进制来表达,就是 1001.101,或者表达成 1.001101×2^3如果尾数不是0 或5,比如 9.624,你就无法用一个二进制数来精确表达,结果只好在取值允许的范围内进行四舍五入。

    5、 如何解决?

    浮点数类型是把十进制数转换成二进制数存储,DECIMAL是把十进制数的整数部分和小数部分拆开,分别转换成十六进制数,进行存储。这样,所有的数值,就都可以精准表达了,不会存在因为无法表达而损失精度的问题。MySQL 用 DECIMAL(M,D)的方式表示高精度小数。其中,M 表示整数部分加小数部分,M<=65。D 表示小数部分位数,D<M

    6、方案验证

    (1)把字段“price”的数据类型修改为 DECIMAL(5,2)

    ALTER TABLE demo.goodsmaster MODIFY COLUMN price DECIMAL(5,2);

     (2)查看数据,并把两个商品价格相加

    7、总结

    (1)浮点类型取值范围大,但是不精准,适用于需要取值范围大,又可以容忍微小误差的科学计算场景,比如计算化学、分子建模、流体动力学等。

    (2)定点数类型取值范围相对小,但是精准,没有误差,适合于对精度要求极高的场景,比如涉及金额计算的场景。

  • 相关阅读:
    相机传感器
    Avalonia开发(一)环境搭建
    信息学奥赛一本通:1311:【例2.5】求逆序对
    .NET Emit 入门教程:第四部分:构建类型(Type)
    工业智能网关BL110详解之1:实现三菱 PLC FX1S 接入Modbus TCP Server云平台
    CVPR 2023 | 达摩院REALY头部重建榜单冠军模型HRN解读
    手写一个简单的Spring容器(原理+源码)
    多个服务器之间免密登录
    Java百题大战
    leetcode 518. 零钱兑换 II、377. 组合总和 Ⅳ
  • 原文地址:https://blog.csdn.net/weibo1230123/article/details/125467963