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 相关文章推荐
BBS(php &amp; mysql)完整版(六)
Oct 09 PHP
php获取mysql版本的几种方法小结
Mar 25 PHP
PHP下使用CURL方式POST数据至API接口的代码
Feb 14 PHP
Windows下的PHP安装文件线程安全和非线程安全的区别
Apr 23 PHP
php实例分享之mysql数据备份
May 19 PHP
PHP5.5和之前的版本empty函数的不同之处
Jun 13 PHP
PHP闭包函数传参及使用外部变量的方法
Mar 15 PHP
深入讲解PHP的Yii框架中的属性(Property)
Mar 18 PHP
WordPress分页伪静态加html后缀
Jun 08 PHP
php cookie工作原理与实例详解
Jul 18 PHP
PHP基于堆栈实现的高级计算器功能示例
Sep 15 PHP
浅谈PHP封装CURL
Mar 06 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在特殊字符前加斜杠的实现代码
2011/07/17 PHP
完美解决phpdoc导出文档中@package的warning及Error的错误
2016/05/17 PHP
PHP实现的随机红包算法示例
2017/08/14 PHP
实例分析PHP中PHPMailer发邮件
2017/12/13 PHP
PHP生成图表pChart的示例解析
2020/07/31 PHP
node.js中的fs.existsSync方法使用说明
2014/12/17 Javascript
Angularjs中的事件广播 —全面解析$broadcast,$emit,$on
2016/05/17 Javascript
jQuery实现为LI列表前3行设置样式的方法【2种方法】
2016/09/04 Javascript
Vue.js路由组件vue-router使用方法详解
2016/12/02 Javascript
angularjs+bootstrap实现自定义分页的实例代码
2017/06/19 Javascript
gulp教程_从入门到项目中快速上手使用方法
2017/09/14 Javascript
详解webpack + vue + node 打造单页面(入门篇)
2017/09/23 Javascript
使用socket.io制做简易WEB聊天室
2018/01/02 Javascript
vue webpack打包优化操作技巧
2018/02/22 Javascript
vue-infinite-loading2.0 中文文档详解
2018/04/08 Javascript
Vue渲染过程浅析
2019/03/14 Javascript
ES6 Object属性新的写法实例小结
2019/06/25 Javascript
微信小程序转化为uni-app项目的方法示例
2020/05/22 Javascript
Python操作json数据的一个简单例子
2014/04/17 Python
python中lambda函数 list comprehension 和 zip函数使用指南
2014/09/28 Python
Python中利用sqrt()方法进行平方根计算的教程
2015/05/15 Python
python+ffmpeg视频并发直播压力测试
2018/03/06 Python
用Python一键搭建Http服务器的方法
2018/06/01 Python
Python装饰器用法实例分析
2019/01/14 Python
Python编译成.so文件进行加密后调用的实现
2019/12/23 Python
DJI全球:DJI Global
2021/03/15 全球购物
Java面试题:说出如下代码的执行结果
2015/10/30 面试题
护士检查书
2014/01/17 职场文书
大二自我鉴定
2014/01/31 职场文书
四风存在的原因分析
2014/02/11 职场文书
商学院大学生求职的自我评价
2014/03/12 职场文书
职称评定自我鉴定
2014/03/18 职场文书
党员学习正风肃纪思想汇报
2014/09/12 职场文书
SQLServer2008提示评估期已过解决方案
2021/04/12 SQL Server
Eclipse+Java+Swing+Mysql实现电影购票系统(详细代码)
2022/01/18 Java/Android
Vscode中SSH插件如何远程连接Linux
2022/05/02 Servers