php 浮点数比较方法详解


Posted in PHP onMay 05, 2017

浮点数运算精度问题

首先看一个例子:

<?php
$a = 0.1;
$b = 0.9;
$c = 1;
var_dump(($a+$b)==$c);
var_dump(($c-$b)==$a);
?>

$a+$b==$c 返回true,正确
$c-$b==$a 返回false,错误

为什么会这样呢?

运算后,精度为20位时实际返回的内容如下:

<?php
$a = 0.1;
$b = 0.9;
$c = 1;
printf("%.20f", $a+$b); // 1.00000000000000000000
printf("%.20f", $c-$b); // 0.09999999999999997780
?>

$c-$b 为 0.09999999999999997780,因此与0.1比较返回false

出现这个问题是因为浮点数计算涉及精度,当浮点数转为二进制时有可能会造成精度丢失。

浮点数转二进制方法

整数部分采用除以2取余方法

小数部分采用乘以2取整方法

例如:把数字8.5转为二进制

整数部分是8

8/2=4 8%2=0
4/2=2 4%2=0
2/2=1 2%2=0

1比2小,因此不需要计算下去,整数8的二进制为 1000

小数部分是0.5

0.5x2 = 1.0

因取整后小数部分为0,因此不需要再计算下去

小数0.5的二进制为 0.1

8.5的二进制为1000.1

计算数字0.9的二进制

0.9x2=1.8
0.8x2=1.6
0.6x2=1.2
0.2x2=0.4
0.4x2=0.8
0.8x2=1.6

…. 之后不断循环下去,当截取精度为N时,N后的数会被舍去,导致精度丢失。

上例中0.9在转为二进制时精度丢失,导致比较时出现错误。

所以永远不要相信浮点数已精确到最后一位,也永远不要比较两个浮点数是否相等。

正确比较浮点数的方法

1.使用round方法处理后再比较

例子:

<?php
$a = 0.1;
$b = 0.9;
$c = 1;
var_dump(($c-$b)==$a);          // false
var_dump(round(($c-$b),1)==round($a,1)); // true
?>

2.使用高精度运算方法

首先进行运算时,使用高精度的运算方法,这样可以保证精度不丢失。

高精度运算的方法如下:

bcadd 将两个高精度数字相加

bccomp 比较两个高精度数字,返回-1,0,1

bcdiv 将两个高精度数字相除

bcmod 求高精度数字余数

bcmul 将两个高精度数字相乘

bcpow 求高精度数字乘方

bcpowmod 求高精度数字乘方求模

bcscale 配置默认小数点位数,相当于Linux bc中的”scale=”

bcsqrt 求高精度数字平方根

bcsub 将两个高精度数字相减

例子:

<?php
$a = 0.1;
$b = 0.9;
$c = 1;
var_dump(($c-$b)==$a);     // false
var_dump(bcsub($c, $b, 1)==$a); // true
?>

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

PHP 相关文章推荐
PHP树的代码,可以嵌套任意层
Oct 09 PHP
html中select语句读取mysql表中内容
Oct 09 PHP
php实现的MySQL通用查询程序
Mar 11 PHP
PHP+MYSQL 出现乱码的解决方法
Aug 08 PHP
php实现可以设置中奖概率的抽奖程序代码分享
Jan 19 PHP
PHP采集类Snoopy抓取图片实例
Jun 19 PHP
PHP 反射(Reflection)使用实例
May 12 PHP
PHP编程获取各个时间段具体时间的方法
May 26 PHP
PHP parse_ini_file函数的应用与扩展操作示例
Jan 07 PHP
PHP文件上传小程序 适合初学者学习!
May 23 PHP
关于PHP求解三数之和问题详析
Nov 09 PHP
详解PHP Swoole与TCP三次握手
May 27 PHP
PHP删除二维数组中相同元素及数组重复值的方法示例
May 05 #PHP
完美解决在ThinkPHP控制器中命名空间的问题
May 05 #PHP
Yii2配置Nginx伪静态的方法
May 05 #PHP
php生成网页桌面快捷方式
May 05 #PHP
php 如何设置一个严格控制过期时间的session
May 05 #PHP
php 数组元素快速去重
May 05 #PHP
Yii2实现自定义独立验证器的方法
May 05 #PHP
You might like
配置PHP使之能同时支持GIF和JPEG
2006/10/09 PHP
php上传文件的增强函数
2010/07/21 PHP
zend framework框架中url大小写问题解决方法
2014/08/19 PHP
thinkPHP中create方法与令牌验证实例浅析
2015/12/08 PHP
laravel实现简单用户权限的示例代码
2019/05/28 PHP
Yii框架常见缓存应用实例小结
2019/09/09 PHP
js变量作用域及可访问性的探讨
2006/11/23 Javascript
JavaScript 原型链学习总结
2010/10/29 Javascript
兼容Firefox的Javascript XSLT 处理XML文件
2014/12/31 Javascript
JS实现图片剪裁并预览效果
2016/08/12 Javascript
炫酷的js手风琴效果
2016/10/13 Javascript
Vue2.0实现1.0的搜索过滤器功能实例代码
2017/03/20 Javascript
Vue实战之vue登录验证的实现代码
2017/10/31 Javascript
简单的vuex 的使用案例笔记
2018/04/13 Javascript
浅谈vux之x-input使用以及源码解读
2018/11/04 Javascript
jQuery的ztree仿windows文件新建和拖拽功能的实现代码
2018/12/05 jQuery
js中Array对象的常用遍历方法详解
2019/01/17 Javascript
react quill中图片上传由默认转成base64改成上传到服务器的方法
2019/10/30 Javascript
Vue基于iview实现登录密码的显示与隐藏功能
2020/03/06 Javascript
JavaScript随机数的组合问题案例分析
2020/05/16 Javascript
ant design的table组件实现全选功能以及自定义分页
2020/11/17 Javascript
Python的Bottle框架中实现最基本的get和post的方法的教程
2015/04/30 Python
python anaconda 安装 环境变量 升级 以及特殊库安装的方法
2017/06/21 Python
Python列表推导式、字典推导式与集合推导式用法实例分析
2018/02/07 Python
tensorflow学习笔记之简单的神经网络训练和测试
2018/04/15 Python
python保存二维数组到txt文件中的方法
2018/11/15 Python
jupyter notebook 中输出pyecharts图实例
2020/04/23 Python
使用Pandas将inf, nan转化成特定的值
2019/12/19 Python
Python实现桌面翻译工具【新手必学】
2020/02/12 Python
opencv中图像叠加/图像融合/按位操作的实现
2020/04/01 Python
巴基斯坦电子产品购物网站:Home Shopping
2017/09/14 全球购物
adidas菲律宾官网:adidas PH
2020/02/07 全球购物
生物科学专业个人求职信范文
2013/12/05 职场文书
2014年两会学习心得体会
2014/03/17 职场文书
小学领导班子对照材料
2014/08/23 职场文书
2016年读书月活动总结范文
2016/04/06 职场文书