PHP浮点数精度问题

PHP常见的浮点数“bug”

<?php
    $f = 0.58;
    var_dump(intval($f * 100)); //为啥输出57

浮点数的表示形式

浮点数的表示(IEEE 754):

  • 浮点数, 以64位的长度(双精度)为例, 会采用1位符号位(E), 11指数位(Q), 52位尾数(M)表示(一共64位).
  • 符号位:最高位表示数据的正负,0表示正数,1表示负数。
  • 指数位:表示数据以2为底的幂,指数采用偏移码表示
  • 尾数:表示数据小数点后的有效数字.

小数的二进制表示方式

下面我们具体计算一下0.58的小数表示过程
0.58 * 2 = 1.16 —————— 1
0.16 * 2 = 0.32 —————— 0
0.32 * 2 = 0.64 —————— 0
0.64 * 2 = 1.28 —————— 1
0.28 * 2 = 0.56 —————— 0
0.56 * 2 = 1.12 —————— 1
0.12 * 2 = 0.24 —————— 0
……
0.58 对于二进制表示来说, 是无限长的值

0.58的二进制表示基本上(52位)是: 1001010001111010111000010100011110101110000101000111

如果0.58只是通过这52位计算的话是:

0.58 -> 0.57999999999999996

所以0.58 * 100 = 57.9999999……

精准的浮点数

    $x = 8 - 7.74;
    $y = 0.26;
    var_dump($x == $y); // false
    $x = 8 - 7.75;
    $y = 0.25;
    var_dump($x == $y); //  true

0.25的二进制表示0.01,0.26的二进制表示0.0100001……,所以0.25是精准的,而0.26不是。

参考:https://www.laruence.com/2013/03/26/2884.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容