PHP 什么情况下 5.590 小于 5.59 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
solaro
V2EX    PHP

PHP 什么情况下 5.590 小于 5.59

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

    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
    gclve  
       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 4:12:15 +08:00
    @stabc 链接 500 Internal Server Error
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     933 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 21:44 PVG 05:44 LAX 13:44 JFK 16:44
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86