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
php中的实现trim函数代码
Mar 19 PHP
php模板中出现空行解决方法
Mar 08 PHP
php无限分类且支持输出树状图的详细介绍
Jun 19 PHP
php 去除html标记--strip_tags与htmlspecialchars的区别详解
Jun 26 PHP
php获取bing每日壁纸示例分享
Feb 25 PHP
php实现将任意进制数转换成10进制的方法
Apr 17 PHP
PHP屏蔽关键字实现方法
Nov 17 PHP
探究Laravel使用env函数读取环境变量为null的问题
Dec 06 PHP
PHP正则表达式匹配替换与分割功能实例浅析
Feb 04 PHP
PHP实现的支付宝支付功能示例
Mar 26 PHP
PHP swoole和redis异步任务实现方法分析
Aug 12 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
完美实现GIF动画缩略图的php代码
2011/01/02 PHP
PHP 提取图片img标记中的任意属性的简单实例
2013/12/10 PHP
codeigniter中测试通过的分页类示例
2014/04/17 PHP
php导出CSV抽象类实例
2014/09/24 PHP
PHP中Memcache操作类及用法实例
2014/12/12 PHP
PHP处理会话函数大总结
2015/08/05 PHP
PHP 5.6.11 访问SQL Server2008R2的几种情况详解
2016/08/08 PHP
PHP错误和异常处理功能模块示例
2016/11/12 PHP
thinkphp3.2实现跨控制器调用其他模块的方法
2017/03/14 PHP
详解使用php调用微信接口上传永久素材
2017/04/11 PHP
php设计模式之装饰模式应用案例详解
2019/06/17 PHP
繁简字转换功能
2006/07/19 Javascript
jQuery EasyUI NumberBox(数字框)的用法
2010/07/08 Javascript
ExtJs使用总结(非常详细)
2012/03/22 Javascript
firefox下jquery iframe刷新页面提示会导致重复之前动作
2012/12/17 Javascript
js实现浏览器的各种菜单命令比如打印、查看源文件等等
2013/10/24 Javascript
JavaScript获取网页中第一个图片id的方法
2015/04/03 Javascript
原生js实现焦点轮播图效果
2017/01/12 Javascript
详解Vue路由History mode模式中页面无法渲染的原因及解决
2017/09/28 Javascript
vue 的点击事件获取当前点击的元素方法
2018/09/15 Javascript
了解JavaScript函数中的默认参数
2019/05/30 Javascript
详解Nuxt.js中使用Element-UI填坑
2019/09/06 Javascript
vue-router之解决addRoutes使用遇到的坑
2020/07/19 Javascript
Django 使用Ajax进行前后台交互的示例讲解
2018/05/28 Python
python 读取目录下csv文件并绘制曲线v111的方法
2018/07/06 Python
利用python实现简易版的贪吃蛇游戏(面向python小白)
2018/12/30 Python
python 实现读取一个excel多个sheet表并合并的方法
2019/02/12 Python
Django rstful登陆认证并检查session是否过期代码实例
2019/08/13 Python
Python 多线程其他属性以及继承Thread类详解
2019/08/28 Python
乌克兰最大的家用电器和电子产品连锁店:Eldorado
2019/10/02 全球购物
兰蔻俄罗斯官方网站:Lancome俄罗斯
2019/12/09 全球购物
Android面试题附答案
2014/12/08 面试题
学年自我鉴定
2014/01/16 职场文书
春节联欢会策划方案
2014/05/16 职场文书
电子信息工程专业求职信
2014/06/28 职场文书
Python3接口性能测试实例代码
2021/06/20 Python