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

一个关于数值计算的奇怪问题

  •  
  •   evil4 · 2021-02-19 14:33:06 +08:00 · 1844 次点击
    这是一个创建于 1369 天前的主题,其中的信息可能已经有所发展或是发生改变。
    今天在处理一个 BUG 的时候,发现了一个很奇怪的问题,写出来让大家参观一下,可能大家也碰到过类似问题,可以讨论一下解决方法以避免后来的同学踩坑。

    问题如下:
    intval(157.2*100)

    我们直观看的话应该觉得输出 15720,但是他实际输出是 15719

    我分别输出 157.2 * 100, 结果 15720
    然后 intval(15720) 结果 15720

    但是为什么上面这个就会输出 15719 呢?有高手指点一下吗?
    9 条回复    2021-02-20 09:21:31 +08:00
    carity
        1
    carity  
       2021-02-19 14:36:00 +08:00
    浮点精度问题
    fengpan567
        2
    fengpan567  
       2021-02-19 14:56:06 +08:00
    转成整数进行计算
    joesonw
        3
    joesonw  
       2021-02-19 14:57:53 +08:00
    eastphoton
        4
    eastphoton  
       2021-02-19 15:00:53 +08:00
    日经了。十进制下的有限小数可能是二进制下的无限循环小数,存不了。

    0.2D=0.00110011B 无限循环,从浮点可存储位数截断后变成 0.19xxx


    不允许误差不要用浮点。
    mrgeneral
        5
    mrgeneral  
       2021-02-19 15:03:38 +08:00
    > 以十进制能够精确表示的有理数如 0.1 或 0.7,无论有多少尾数都不能被内部所使用的二进制精确表示,因此不能在不丢失一点点精度的情况下转换为二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999999991118...。

    如果确实需要更高的精度,应该使用 BC 或者 GMP 。
    debuggerx
        6
    debuggerx  
       2021-02-19 15:04:02 +08:00
    round()
    zhengwenk
        7
    zhengwenk  
       2021-02-19 16:13:00 +08:00
    var_dump(157.2 * 100)
    float(15720)

    157.2*100 === 15720
    false
    Jooooooooo
        8
    Jooooooooo  
       2021-02-20 00:00:09 +08:00
    有些十进制看起来可以表达, 其实二进制表达不了.
    Rache1
        9
    Rache1  
       2021-02-20 09:21:31 +08:00
    换成 BC Math 方法。
    bcmul('157.2',100,0)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3107 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 00:35 · PVG 08:35 · LAX 16:35 · JFK 19:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.