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 相关文章推荐
?生?D片??C字串
Dec 06 PHP
PHP读取RSS(Feed)简单实例
Jun 12 PHP
ThinkPHP CURD方法之table方法详解
Jun 18 PHP
PHP生成数组再传给js的方法
Aug 07 PHP
php批量删除数据库下指定前缀的表以prefix_为例
Aug 24 PHP
PHP实现数组递归转义的方法
Aug 28 PHP
使用PHP如何实现高效安全的ftp服务器(二)
Dec 30 PHP
Laravel执行migrate命令提示:No such file or directory的解决方法
Mar 16 PHP
Windows Server 2008 R2和2012中PHP连接MySQL过慢的解决方法
Jul 02 PHP
php验证码生成器
May 24 PHP
PHP实现将几张照片拼接到一起的合成图片功能【便于整体打印输出】
Nov 14 PHP
利用PHP计算有多少小于当前数字的数字方法示例
Aug 26 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+MYSQL 出现乱码的解决方法
2008/08/08 PHP
php $_SERVER windows系统与linux系统下的区别说明
2014/02/14 PHP
PHP图像处理之使用imagecolorallocate()函数设置颜色例子
2014/11/19 PHP
PHP对象克隆clone用法示例
2016/09/28 PHP
php文件包含目录配置open_basedir的使用与性能详解
2017/04/03 PHP
Yii 访问 Gii(脚手架)时出现 403 错误
2018/06/06 PHP
google 搜索框添加关键字实现代码
2010/04/24 Javascript
jQuery中创建实例与原型继承揭秘
2011/12/21 Javascript
JS 加入收藏夹的代码(主流浏览器通用)
2013/05/13 Javascript
js控制的遮罩层实例介绍
2013/05/29 Javascript
display和visibility的区别示例介绍
2014/02/26 Javascript
JavaScript取得WEB安全颜色列表的方法
2015/07/14 Javascript
javascript密码强度校验代码(两种方法)
2015/08/10 Javascript
浅谈javascript的Array.prototype.slice.call
2015/08/31 Javascript
jQuery无刷新上传之uploadify简单代码
2017/01/17 Javascript
浅谈vue实现数据监听的函数 Object.defineProperty
2017/06/08 Javascript
不使用 JS 匿名函数理由
2017/11/17 Javascript
详解mpvue小程序中怎么引入iconfont字体图标
2018/10/01 Javascript
如何使用50行javaScript代码实现简单版的call,apply,bind
2019/08/14 Javascript
解决LayUI数据表格复选框不居中显示的问题
2019/09/25 Javascript
浅谈vue3中effect与computed的亲密关系
2019/10/10 Javascript
vue-路由精讲 二级路由和三级路由的作用
2020/08/06 Javascript
微信小程序抽奖组件的使用步骤
2021/01/11 Javascript
[02:05]2014DOTA2西雅图邀请赛 老队长全明星大猜想谁不服就按进显示器
2014/07/08 DOTA
python实现TCP服务器端与客户端的方法详解
2015/04/30 Python
Python安装lz4-0.10.1遇到的坑
2018/05/20 Python
Python 通过调用接口获取公交信息的实例
2018/12/17 Python
解决python xx.py文件点击完之后一闪而过的问题
2019/06/24 Python
Python获取时间范围内日期列表和周列表的函数
2019/08/05 Python
解决安装新版PyQt5、PyQT5-tool后打不开并Designer.exe提示no Qt platform plugin的问题
2020/04/24 Python
Java程序员面试题
2013/07/15 面试题
《赵州桥》教学反思
2014/02/17 职场文书
企业文化宣传标语
2014/06/09 职场文书
中学图书馆工作总结
2015/08/11 职场文书
运动会主持人开幕词
2016/03/04 职场文书
六年级作文之自救
2019/12/19 职场文书