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 相关文章推荐
1.PHP简介
Oct 09 PHP
用PHP ob_start()控制浏览器cache、生成html实现代码
Feb 16 PHP
php下pdo的mysql事务处理用法实例
Dec 27 PHP
php实现猴子选大王问题算法实例
Apr 20 PHP
PHP查找与搜索数组元素方法总结
Jun 12 PHP
php中ob函数缓冲机制深入理解
Aug 03 PHP
全面解读PHP的Yii框架中的日志功能
Mar 17 PHP
详解PHP使用Redis存储session时的一个Warning定位
Jul 05 PHP
yii框架redis结合php实现秒杀效果(实例代码)
Oct 26 PHP
PHP+百度AI OCR文字识别实现了图片的文字识别功能
May 08 PHP
PHP 文件上传限制问题
Sep 01 PHP
PHP7原生MySQL数据库操作实现代码
Jul 03 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 字符串 小常识
2009/06/05 PHP
PHP工程师VIM配置分享
2015/12/15 PHP
PHP实现简单的模板引擎功能示例
2017/09/02 PHP
一段利用WSH获取登录时间的jscript代码
2008/05/11 Javascript
各种效果的jquery ui(接口)介绍
2008/09/17 Javascript
关于juqery radio写法的兼容性问题(新老版本jquery)
2010/06/14 Javascript
基于jQuery的让非HTML5浏览器支持placeholder属性的代码
2011/05/24 Javascript
jQuery实现渐变下拉菜单的简单方法
2015/03/11 Javascript
谈谈jQuery之Deferred源码剖析
2016/12/19 Javascript
js监听input输入框值的实时变化实例
2017/01/26 Javascript
MUI 上拉刷新/下拉加载功能实例代码
2017/04/13 Javascript
强大的 Angular 表单验证功能详细介绍
2017/05/23 Javascript
vue实现商城上货组件简易版
2017/11/27 Javascript
Vue中 key keep-alive的实现原理
2018/09/18 Javascript
微信小程序冒泡事件及其阻止方法实例分析
2018/12/06 Javascript
详解在Angular4中使用ng2-baidu-map的方法
2019/06/19 Javascript
[01:23:35]Ti4主赛事胜者组 DK vs EG 1
2014/07/19 DOTA
python文件特定行插入和替换实例详解
2017/07/12 Python
Python中对象的引用与复制代码示例
2017/12/04 Python
使用python3+xlrd解析Excel的实例
2018/05/04 Python
Python3 读、写Excel文件的操作方法
2018/10/20 Python
Pycharm安装并配置jupyter notebook的实现
2020/05/18 Python
keras使用Sequence类调用大规模数据集进行训练的实现
2020/06/22 Python
python+django+selenium搭建简易自动化测试
2020/08/19 Python
CSS3中使用RGBA设置透明度的示例
2015/08/04 HTML / CSS
印度网上购物首选目的地:Flipkart
2016/08/01 全球购物
服装促销活动方案
2014/02/23 职场文书
导游个人求职信范文
2014/03/23 职场文书
党支部公开承诺践诺书
2014/03/28 职场文书
大学生毕业求职信
2014/06/12 职场文书
美德少年事迹材料1000字
2014/08/21 职场文书
学校个人对照检查材料
2014/08/26 职场文书
课外小组活动总结
2014/08/27 职场文书
2015年党日活动总结范文
2015/03/25 职场文书
观后感格式
2015/06/19 职场文书
python库Tsmoothie模块数据平滑化异常点抓取
2022/06/10 Python