千家信息网

PHP浮点数精度问题总结

发表于:2025-01-16 作者:千家信息网编辑
千家信息网最后更新 2025年01月16日,这篇文章主要介绍"PHP浮点数精度问题总结",在日常操作中,相信很多人在PHP浮点数精度问题总结问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"PHP浮点数精度问题总结"
千家信息网最后更新 2025年01月16日PHP浮点数精度问题总结

这篇文章主要介绍"PHP浮点数精度问题总结",在日常操作中,相信很多人在PHP浮点数精度问题总结问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"PHP浮点数精度问题总结"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、PHP浮点数精度损失问题

先看下面这段代码:

$f = 0.57;
echo intval($f * 100); //56

结果可能有点出乎你的意外,PHP遵循IEEE 754双精度:

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

再来看看小数用二进制怎么表示:

乘2取整,顺序排列,即将小数部分乘以2,然后取整数部分,剩下的小数部分继续乘以2,然后取整数部分,剩下的小数部分又乘以2,一直取到小数部分,但是像0.57这样的小数像这样一直乘下去,小数部分不可能为0.有效位的小数用二进制表示却是无穷的。

0.57的二进制表示基本上(52位)是: 0010001111010111000010100011110101110000101000111101

如果只有52位的话,0.57 =》 0.56999999999999995

不难看出上面意外的结果了吧。

二、PHP浮点数的精度问题

先看问题:

复制代码 代码如下:


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

我相信有很多的同学有过这样的疑问。

具体原理可阅读"鸟哥"的一篇文章,那里有详细的解说:PHP浮点数的一个常见问题的解答

那么如何避免这种问题呢?
办法有很多,这里列举两个:
1. sprintf

复制代码 代码如下:


substr(sprintf("%.10f", ($a/ $b)), 0, -7);


2. round (注意会进行四舍五入)

复制代码 代码如下:


round($a/$b, 3);


或者你有更好的办法,也可以了留言告诉我。

三、PHP浮点数的一个常见问题的解答

关于PHP的浮点数, 我之前写过一篇文章: 关于PHP浮点数你应该知道的(All 'bogus' about the float in PHP)

不过, 我当时遗漏了一点, 也就是对于如下的这个常见问题的回答:

复制代码 代码如下:


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


为啥输出是57啊? PHP的bug么?

我相信有很多的同学有过这样的疑问, 因为光问我类似问题的人就很多, 更不用说bugs.php.net上经常有人问…

要搞明白这个原因, 首先我们要知道浮点数的表示(IEEE 754):

浮点数, 以64位的长度(双精度)为例, 会采用1位符号位(E), 11指数位(Q), 52位尾数(M)表示(一共64位).

符号位:最高位表示数据的正负,0表示正数,1表示负数。

指数位:表示数据以2为底的幂,指数采用偏移码表示

尾数:表示数据小数点后的有效数字.

这里的关键点就在于, 小数在二进制的表示, 关于小数如何用二进制表示, 大家可以百度一下, 我这里就不再赘述, 我们关键的要了解, 0.58 对于二进制表示来说, 是无限长的值(下面的数字省掉了隐含的1)..

0.58的二进制表示基本上(52位)是: 0010100011110101110000101000111101011100001010001111
0.57的二进制表示基本上(52位)是: 0010001111010111000010100011110101110000101000111101
而两者的二进制, 如果只是通过这52位计算的话,分别是:

复制代码 代码如下:


0.58 -> 0.57999999999999996
0.57 -> 0.56999999999999995


至于0.58 * 100的具体浮点数乘法, 我们不考虑那么细, 有兴趣的可以看(Floating point), 我们就模糊的以心算来看… 0.58 * 100 = 57.999999999

那你intval一下, 自然就是57了….

到此,关于"PHP浮点数精度问题总结"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

点数 问题 小数 代码 精度 二进制 部分 数据 尾数 数位 符号 学习 有效 常见 常见问题 数字 篇文章 解答 输出 最高 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 高校网络安全守则 深圳宝安区招聘网络技术人员 珠海利他互联网科技 阜阳市校园网络安全管理实施办法 社交网络安全专业词汇 华为云数据库的默认端口 数据库版本号控制加锁 网络安全技术措施落实情况 苹果云空间连接到服务器出现问题 如何将游戏加入到服务器 云服务器可以重置吗 北京服务器阵列卡驱动云主机 数据库与服务器设计 松江区管理网络技术服务哪家好 powerdesigner连接mysql数据库 carsim 数据库 苹果11手机发件服务器怎么填写 u8 数据库表结构 联想sr258服务器配置 绝地求生香港服务器在哪 电信服务器价格 四川多媒体软件开发 综合管理平台服务器价格 数据库与网站建设视频教程 网络安全贵州大学考试试卷 企业网络安全方案内容 如何提取带单位的数据库 mstsc服务器管理工具 打电话显示无法连接到服务器 系统软件开发流程管理软件
0