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边学边教》(04.编写简易的通讯录――视频教程1)
Dec 13 PHP
php下删除字符串中HTML标签的函数
Aug 27 PHP
允许phpmyadmin空密码登录的配置方法
May 29 PHP
mac下安装nginx和php
Nov 04 PHP
php基于GD库画五星红旗的方法
Feb 24 PHP
Ubuntu中搭建Nginx、PHP环境最简单的方法
Mar 05 PHP
深入理解PHP JSON数组与对象
Jul 19 PHP
PHP图像识别技术原理与实现
Oct 27 PHP
根据key删除数组中指定的元素实现方法
Mar 02 PHP
PHP实现的自定义图像居中裁剪函数示例【测试可用】
Aug 11 PHP
PHP超低内存遍历目录文件和读取超大文件的方法
May 01 PHP
gearman管理工具GearmanManager的安装与php使用方法示例
Feb 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限制上传文件类型并保存上传文件的方法
2015/03/13 PHP
PHP提高编程效率的20个要点
2015/09/23 PHP
PHP实现微信JS-SDK接口选择相册及拍照并上传的方法
2016/12/05 PHP
smarty模板数学运算示例
2016/12/11 PHP
javascript 页面划词搜索JS
2009/09/28 Javascript
判断用户的在线状态 onbeforeunload事件
2011/03/05 Javascript
jQuery 三击事件实现代码
2013/09/11 Javascript
原生JS实现加入收藏夹的代码
2013/10/24 Javascript
Javascript单元测试框架QUnitjs详细介绍
2014/05/08 Javascript
jQuery检测滚动条是否到达底部
2015/12/15 Javascript
基于javascript html5实现多文件上传
2016/03/03 Javascript
javaScript中的原型解析【推荐】
2016/05/05 Javascript
js中 计算两个日期间的工作日的简单实例
2016/08/08 Javascript
bootstrap多种样式进度条展示
2016/12/20 Javascript
函数四种调用模式以及其中的this指向
2017/01/16 Javascript
微信小程序实战之运维小项目
2017/01/17 Javascript
微信小程序三级联动地址选择器的实例代码
2017/07/12 Javascript
jQuery实现的淡入淡出图片轮播效果示例
2018/08/29 jQuery
jQuery事件blur()方法的使用实例讲解
2019/03/30 jQuery
如何基于filter实现网站整体变灰功能
2020/04/17 Javascript
在vs code 中如何创建一个自己的 Vue 模板代码
2020/11/10 Javascript
[47:10]完美世界DOTA2联赛PWL S3 LBZS vs Rebirth 第二场 12.16
2020/12/18 DOTA
python实现在pickling的时候压缩的方法
2014/09/25 Python
在Python的web框架中配置app的教程
2015/04/30 Python
剖析Django中模版标签的解析与参数传递
2015/07/21 Python
举例讲解Python中的死锁、可重入锁和互斥锁
2015/11/05 Python
利用Python爬虫给孩子起个好名字
2017/02/14 Python
Python用csv写入文件_消除空余行的方法
2018/07/06 Python
Flask配置Cors跨域的实现
2019/07/12 Python
Python autoescape标签用法解析
2020/01/17 Python
Keras模型转成tensorflow的.pb操作
2020/07/06 Python
英国123鲜花网站:123 Flowers
2019/07/07 全球购物
文化产业实施方案
2014/06/07 职场文书
街道社区活动报告
2015/02/05 职场文书
呐喊读书笔记
2015/06/30 职场文书
员工担保书范本
2015/09/22 职场文书