V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
solaro
V2EX  ›  PHP

PHP 什么情况下 5.590 小于 5.59

  •  
  •   solaro · 2017-07-26 16:51:34 +08:00 · 5074 次点击
    这是一个创建于 2672 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Markdown

    上图实际开发业务中,碰到了个坑,

    数据库用的 mysql 左边 5.590 在数据库中存储是 decimal(10,3) 右边是换算出来的 float

    现在 floatval(5.590) < floatval(5.59)

    我 sun

    43 条回复    2017-07-29 14:12:15 +08:00
    elgae
        1
    elgae  
       2017-07-26 16:56:51 +08:00
    关系到钱的业务用浮点数,心很大。
    7654
        2
    7654  
       2017-07-26 17:00:41 +08:00   ❤️ 3
    有个故事,某企财务将全厂工资的几分零头抹掉,每月可偷几千块
    Jacklee
        3
    Jacklee  
       2017-07-26 17:03:50 +08:00   ❤️ 1
    计算机存储浮点型都不是精确的,如楼上所说,不能直接比较大小啊。涉及钱的业务更不能用啊。
    Jacklee
        4
    Jacklee  
       2017-07-26 17:04:25 +08:00
    补一句,这不是 PHP 的锅哈
    oh
        5
    oh  
       2017-07-26 17:09:27 +08:00   ❤️ 1
    抛去楼上已解决说的,不知道楼主有没有试过在 if 前面 var_dump(floatval()) 看看这两个变量对比的时候是多少?
    Biscuits
        6
    Biscuits  
       2017-07-26 17:12:44 +08:00   ❤️ 2
    5.59 可能是 5.5904444
    bombless
        7
    bombless  
       2017-07-26 17:12:46 +08:00   ❤️ 1
    比较的时候乘 100 按整数比吧
    lujiajing1126
        8
    lujiajing1126  
       2017-07-26 17:12:52 +08:00 via iPhone
    楼主需要复习一下 IEEE754
    goodspb
        9
    goodspb  
       2017-07-26 17:12:56 +08:00
    php > var_dump(floatval(5.590) < floatval(5.59));
    php shell code:1:
    bool(false)
    php > var_dump(floatval(5.590) == floatval(5.59));
    php shell code:1:
    bool(true)
    php > var_dump(5.590 == 5.59);
    php shell code:1:
    bool(true)
    php > var_dump(5.590 < 5.59);
    php shell code:1:
    bool(false)

    恩?有啥问题?

    php -v 一下

    PHP 5.6.30 (cli) (built: Apr 17 2017 10:09:18)
    Copyright (c) 1997-2016 The PHP Group
    Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
    with Xdebug v2.5.3, Copyright (c) 2002-2017, by Derick Rethans
    ovear
        10
    ovear  
       2017-07-26 17:14:02 +08:00   ❤️ 1
    请使用 bccomp
    exch4nge
        11
    exch4nge  
       2017-07-26 17:14:53 +08:00
    对 PHP 不熟悉……不过表示金钱的类型应该用专门的 decimal 类型吧……
    nfroot
        12
    nfroot  
       2017-07-26 17:15:19 +08:00
    @bombless 加减乘除都这样么 0 0
    gclove
        13
    gclove  
       2017-07-26 17:15:50 +08:00
    同上, 计算千万不要用符点, 还不如用大数计算

    建议直接乘 100 取整
    为什么设置 3 位, 你们应用还有微分 ?
    有的话可以乘以 1000 取整

    浮点在每种变成语言都有陷阱(坑), 经验不够老练都会踩上
    gclove
        14
    gclove  
       2017-07-26 17:21:30 +08:00
    非用浮点, 计算前值一定要进行类型转换

    因为你不知道它是 整数, 浮点, 还是 字符串
    solaro
        15
    solaro  
    OP
       2017-07-26 17:21:38 +08:00
    本地开发环境用 5.6.27 没毛病,生产环境用 7.1 就触发异常。。。我日
    doushiyinweini
        16
    doushiyinweini  
       2017-07-26 17:24:10 +08:00   ❤️ 1
    moult
        17
    moult  
       2017-07-26 17:25:36 +08:00
    就算知道什么情况下出现这个问题,那又如何?
    1、从数据库里面查询出来的浮点数,请使用 string。
    2、http://php.net/manual/en/book.bc.php
    3、个人癖好,有段时间,金钱我用 int 来存储,单位是分。不过现在都用 string 来做了。
    solaro
        18
    solaro  
    OP
       2017-07-26 17:31:57 +08:00
    @moult 为什么,请老司机传道受业解惑,int 不够用我可以理解,bigint 不好吗?为什么换 string
    solaro
        19
    solaro  
    OP
       2017-07-26 17:32:46 +08:00
    @elgae 早期留下的坑
    zhs227
        20
    zhs227  
       2017-07-26 17:34:48 +08:00
    涉及到价格我每次都是*100 以后按整数存。float 的比较容易出问题,越相近越容易出问题。
    cnfzv
        21
    cnfzv  
       2017-07-26 17:36:29 +08:00
    @solaro 同问
    ety001
        22
    ety001  
       2017-07-26 17:54:37 +08:00
    之前用过整数(就是存储到分),后来就用 decimal 了。
    oneonesv
        23
    oneonesv  
       2017-07-26 18:00:31 +08:00
    浮点数精度不够 可能会有类似 0.111 != 0.111 的情况

    PHP 文档 浮点数 章节里面有讲
    stabc
        24
    stabc  
       2017-07-26 18:01:02 +08:00
    谁能说下这种浮点数在计算中常见的坑?
    LioMore
        25
    LioMore  
       2017-07-26 18:06:16 +08:00
    请问一下,正确的做法是只用分来计算并使用整数吗?
    azh7138m
        26
    azh7138m  
       2017-07-26 18:44:28 +08:00 via Android
    @LioMore 是的
    maypu
        27
    maypu  
       2017-07-26 18:49:14 +08:00 via Android
    算错的时候,哈哈哈哈哈哈
    a591826944
        28
    a591826944  
       2017-07-26 19:54:37 +08:00
    LZ 你的心真大。。浮点数算金额。。
    a591826944
        29
    a591826944  
       2017-07-26 19:55:11 +08:00   ❤️ 1
    LZ 你试试 floor(8.29 * 100 * 100 / 100) 的结果 体会一下。。。

    这真不是 PHP 的锅、、
    bianchensz
        30
    bianchensz  
       2017-07-26 21:11:56 +08:00   ❤️ 1
    233 就算是我老妈用 excel 涉及到钱的都要套个 round 取整,你这也是心大
    xzem
        31
    xzem  
       2017-07-26 22:10:14 +08:00 via Android
    被浮点坑过一次,再也不敢用浮点做计算 比较了
    blankme
        32
    blankme  
       2017-07-26 22:18:51 +08:00   ❤️ 1
    ```
    if (fabs(a - b) > 1e-3 && a < b)
    ```
    zhx1991
        33
    zhx1991  
       2017-07-26 23:16:42 +08:00   ❤️ 1
    钱用浮点数什么都可能发生

    想追究细节的话了解一下计算机怎么表示小数就明白了
    stabc
        34
    stabc  
       2017-07-26 23:35:50 +08:00   ❤️ 1
    看一下这个明白了:
    https://kknews.cc/tech/p8bpz2p.html
    incompatible
        35
    incompatible  
       2017-07-26 23:42:03 +08:00   ❤️ 4
    @LioMore 不是,不要听本帖的草台班子们胡扯用什么 int。正确的方法是用 decimal。
    PHP 用户可以看一下 http://de2.php.net/manual/en/ref.bc.php
    dikT
        36
    dikT  
       2017-07-26 23:48:08 +08:00   ❤️ 1
    现在想想微信的钱 fee 就是按分来存储.当时觉得很奇怪, 恍然大悟[doge]
    wsy2220
        37
    wsy2220  
       2017-07-26 23:54:47 +08:00
    心真大
    msg7086
        38
    msg7086  
       2017-07-27 00:16:47 +08:00
    浮点数大都是不精确的数据存储。
    比如 5.59 这个数就无法用浮点数表达,因为在二进制中是个无理数。
    LioMore
        39
    LioMore  
       2017-07-27 00:20:13 +08:00
    @incompatible 好的,感谢
    solaro
        40
    solaro  
    OP
       2017-07-27 09:41:38 +08:00
    被坑到了。谢谢各位
    incompatible
        41
    incompatible  
       2017-07-27 18:09:45 +08:00 via iPhone   ❤️ 1
    @solaro int 或 bigint 没法处理小数位数,两个数相除时是要处理结果保留几位小数以及 ceiling(四舍五入 / 去尾 / 进一)的规则的,所以应该用(数学意义上的)decimal。
    那哥们用 string 的原因是 php 这个所谓的最好的语言居然没有内置对 decimal 的支持,而是需要通过 bc extension 处理 string 来实现对 decimal 的操作。
    lestat
        42
    lestat  
       2017-07-28 20:14:58 +08:00 via iPhone
    写个专门运算的函数,全部乘以 100 之后运算,把结果再除以 100 返回,可以参考微信支付的做法
    mingyun
        43
    mingyun  
       2017-07-29 14:12:15 +08:00
    @stabc 链接 500 Internal Server Error
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3603 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 04:40 · PVG 12:40 · LAX 20:40 · JFK 23:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.