PHP中浮点数计算比较及取整不准确的解决方法


Posted in PHP onJanuary 09, 2015

浮点数计算结果比较
一则浮点数计算例子如下:

$a = 0.2+0.7;

$b = 0.9;

var_dump($a == $b);

打印出的结果是:bool(false)。也就是说在这里 0.2+0.7 的计算结果与 0.9 并不相等,这显然是有违我们的常识的。

对此问题,PHP官方手册曾又说明:显然简单的十进制分数如 0.2 不能在不丢失一点点精度的情况下转换为内部二进制的格式。这和一个事实有关,那就是不可能精确的用有限位数表达某些十进制分数。例如,十进制的 1/3 变成了 0.3333333...。

我们将上面的变量用双精度格式打印出来:

$a = 0.2+0.7;

$b = 0.9;

printf("%0.20f", $a);

echo '<br />';

printf("%0.20f", $b);

输出结果如下:

0.89999999999999991118

0.90000000000000002220

显然在这里,实际上作为浮点型数据,其精度已经损失了一部分,达不到完全精确。所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。需要说明的是,这不是PHP的问题,而是计算机内部处理浮点数的问题!在 C、JAVA 等语言中也会遇到同样的问题。

所以要比较两个浮点数,需要将其控制在我们需要的精度范围内再行比较,因此使用 bcadd() 函数来对浮点数想加并进行精度转换(为字符串):

var_dump(bcadd(0.2,0.7,1) == 0.9); // 输出:bool(true)

浮点数取整

在《PHP 取整函数 ceil 与 floor》一文中,曾有例子:

<?php

echo ceil(2.1/0.7);    // 输出:4

?>

经过上面对浮点数计算的探讨,知道这是浮点数计算结果不完全精确造成的:

<?php

printf("%0.20f", (2.1/0.7));    // 输出:3.00000000000000044409

?>

经过上面对浮点数计算的探讨,知道这是浮点数计算结果不完全精确造成的,因此使用 round() 函数处理一下即可:

<?php

echo ceil( round((2.1/0.7),1) );

?>

虽然 round() 函数是按照指定的精度进行四舍五入,但保留小数点后一位,对我们的取整结果是没影响的。

PHP 相关文章推荐
php中看实例学正则表达式
Dec 25 PHP
了解Joomla 这款来自国外的php网站管理系统
Mar 11 PHP
PHP 开发环境配置(测试开发环境)
Apr 28 PHP
php cli换行示例
Apr 22 PHP
PHP函数getenv简介和使用实例
May 12 PHP
CI(CodeIgniter)框架中的增删改查操作
Jun 10 PHP
10条php编程小技巧
Jul 07 PHP
利用“多说”制作留言板、评论系统
Jul 14 PHP
分享10段PHP常用代码
Nov 11 PHP
隐藏Nginx或Apache以及PHP的版本号的方法
Jan 03 PHP
php版阿里云OSS图片上传类详解
Dec 01 PHP
php+redis在实际项目中HTTP 500: Internal Server Error故障排除
Feb 05 PHP
php模拟登陆的实现方法分析
Jan 09 #PHP
php获取四位字母和数字的随机数的实现方法
Jan 09 #PHP
php实现读取手机客户端浏览器的类
Jan 09 #PHP
ucenter通信原理分析
Jan 09 #PHP
PHP上传文件时自动分配路径的方法
Jan 09 #PHP
PHP中new static() 和 new self() 的区别介绍
Jan 09 #PHP
PHP中的替代语法介绍
Jan 09 #PHP
You might like
php&amp;java(二)
2006/10/09 PHP
关于ob_get_contents(),ob_end_clean(),ob_start(),的具体用法详解
2013/06/24 PHP
在PHP中输出JS语句以及乱码问题的解决方案
2019/02/13 PHP
laravel 解决Eloquent ORM的save方法无法插入数据的问题
2019/10/21 PHP
js常用代码段整理
2011/11/30 Javascript
jquery实现导航固定顶部的效果仿蘑菇街
2014/10/22 Javascript
jQuery仅用3行代码实现的显示与隐藏功能完整实例
2015/10/08 Javascript
微信小程序 常用工具类详解及实例
2017/02/15 Javascript
纯js的右下角弹窗实例
2017/03/12 Javascript
整理关于Bootstrap排版的慕课笔记
2017/03/29 Javascript
jQuery实现动态删除LI的方法
2017/05/30 jQuery
es6学习之解构时应该注意的点
2017/08/29 Javascript
详解js静态检查工具eslint配置文件
2018/11/23 Javascript
vue 使用axios 数据请求第三方插件的使用教程详解
2019/07/05 Javascript
ElementUI中el-tree节点的操作的实现
2020/02/27 Javascript
[12:36]《DOTA2》国服注册与激活指南全攻略
2013/04/28 DOTA
Python中生成器和yield语句的用法详解
2015/04/17 Python
Python中list列表的一些进阶使用方法介绍
2015/08/15 Python
解决matplotlib库show()方法不显示图片的问题
2018/05/24 Python
python编辑用户登入界面的实现代码
2018/07/16 Python
Python爬取个人微信朋友信息操作示例
2018/08/03 Python
Python3.5面向对象程序设计之类的继承和多态详解
2019/04/24 Python
keras实现基于孪生网络的图片相似度计算方式
2020/06/11 Python
Flask中sqlalchemy模块的实例用法
2020/08/02 Python
python Protobuf定义消息类型知识点讲解
2021/03/02 Python
ziaja齐叶雅官方海外旗舰店:来自波兰的天然护肤品牌
2017/01/02 全球购物
爱尔兰领先的在线体育用品零售商:theGAAstore
2018/04/16 全球购物
经典的毕业生自荐信范文
2014/04/14 职场文书
2014年学生会干事工作总结
2014/11/07 职场文书
三国演义读书笔记
2015/06/25 职场文书
2015年中秋放假通知范文
2015/08/18 职场文书
会计专业自荐信范文
2019/05/22 职场文书
导游词之西安骊山
2019/12/20 职场文书
MySQL8.0无法启动3534的解决方法
2021/06/03 MySQL
Java字符串逆序方法详情
2022/03/21 Java/Android
mysql使用FIND_IN_SET和group_concat两个方法查询上下级机构
2022/04/20 MySQL