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安装为Apache DSO
Oct 09 PHP
我的论坛源代码(三)
Oct 09 PHP
PHP 时间日期操作实战
Aug 26 PHP
网页上facebook分享功能具体实现
Jan 26 PHP
php格式化日期和时间格式化示例分享
Feb 24 PHP
分享十款最出色的PHP安全开发库中文详细介绍
Mar 22 PHP
composer.lock文件的作用
Feb 03 PHP
Yii 2.0中场景的使用教程
Jun 02 PHP
YII框架中使用memcache的方法详解
Aug 02 PHP
Laravel Eloquent分表方法并使用模型关联的实现
Nov 25 PHP
php设计模式之原型模式分析【星际争霸游戏案例】
Mar 23 PHP
PHP如何解决微信文章图片防盗链
Dec 09 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学习之PHP运算符
2006/10/09 PHP
Zend Studio (eclipse)使用速度优化方法
2011/03/23 PHP
php 购物车完整实现代码
2014/06/05 PHP
PHP并发多进程处理利器Gearman使用介绍
2016/05/16 PHP
PHP的消息通信机制测试实例
2016/11/10 PHP
浅谈PHP中pack、unpack的详细用法
2018/03/12 PHP
兼容多浏览器的iframe自适应高度(ie8 、谷歌浏览器4.0和 firefox3.5.3)
2009/11/04 Javascript
JavaScript下利用fso判断文件是否存在的代码
2010/12/11 Javascript
JavaScript生成SQL查询表单的方法
2015/08/13 Javascript
AngularJS仿苹果滑屏删除控件
2016/01/18 Javascript
JavaScript实现打开链接页面的方式汇总
2016/06/02 Javascript
老生常谈原生JS执行环境与作用域
2016/11/22 Javascript
easyui关于validatebox实现多重规则验证的方法(必看)
2017/04/12 Javascript
React Native如何消除启动时白屏的方法
2017/08/08 Javascript
JavaScript惰性求值的一种实现方法示例
2019/01/11 Javascript
Vue.js 中的实用工具方法【推荐】
2019/07/04 Javascript
微信小程序自定义tabBar在uni-app的适配详解
2019/09/30 Javascript
解决vue的touchStart事件及click事件冲突问题
2020/07/21 Javascript
js和jquery判断数据类型的4种方法总结
2020/08/28 jQuery
vue监听滚动事件的方法
2020/12/21 Vue.js
Python存取XML的常见方法实例分析
2017/03/21 Python
python中使用xlrd读excel使用xlwt写excel的实例代码
2018/01/31 Python
python3基于TCP实现CS架构文件传输
2018/07/28 Python
Python/ArcPy遍历指定目录中的MDB文件方法
2018/10/27 Python
python 伯努利分布详解
2020/02/25 Python
python连接mongodb数据库操作数据示例
2020/11/30 Python
购买瑞典当代设计的腕表和太阳眼镜:TRIWA
2016/10/30 全球购物
体育教育专业自荐信范文
2013/12/20 职场文书
管理提升方案
2014/06/04 职场文书
社区服务活动小结
2014/07/08 职场文书
毕业证丢失证明范本
2014/09/20 职场文书
党的群众路线批评与自我批评范文
2014/10/16 职场文书
白鹤梁导游词
2015/02/06 职场文书
信息技术课教学反思
2016/02/23 职场文书
node.js使用express-fileupload中间件实现文件上传
2021/07/16 Javascript
vue-treeselect的基本用法以及解决点击无法出现拉下菜单
2022/04/30 Vue.js