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中Date获取时间不正确怎么办
Jun 05 PHP
php获取mysql数据库中的所有表名的代码
Apr 23 PHP
php获取服务器信息的实现代码
Feb 04 PHP
使用PHP下载CSS文件中的图片的代码
Sep 24 PHP
php使用qr生成二维码的示例分享
Jan 20 PHP
PHP中常用的转义函数
Feb 28 PHP
windows7下安装php的imagick和imagemagick扩展教程
Jul 04 PHP
在Mac上编译安装PHP7的开发环境
Jul 28 PHP
PHP几个实用自定义函数小结
Jan 25 PHP
浅谈PHP中静态方法和非静态方法的相互调用
Oct 04 PHP
轻松实现php文件上传功能
Feb 17 PHP
PHP设计模式(九)外观模式Facade实例详解【结构型】
May 02 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
win7系统配置php+Apache+mysql环境的方法
2015/08/21 PHP
PHP易混淆知识整理笔记
2015/09/24 PHP
laravel 字段格式化 modle 字段类型转换方法
2019/09/30 PHP
可以文本显示的公告栏的js代码
2007/03/11 Javascript
javascript学习基础笔记之DOM对象操作
2011/11/03 Javascript
JS特权方法定义作用以及与公有方法的区别
2013/03/18 Javascript
简单的JavaScript互斥锁分享
2014/02/02 Javascript
jQuery实现checkbox即点即改批量删除及中间遇到的坑
2017/11/11 jQuery
详解IWinter 一个路由转控制器的 Nodejs 库
2017/11/15 NodeJs
浅谈ajax在jquery中的请求和servlet中的响应
2018/01/22 jQuery
解决JS表单验证只有第一个IF起作用的问题
2018/12/04 Javascript
JSX在render函数中的应用详解
2019/09/04 Javascript
Vue数字输入框组件示例代码详解
2020/01/15 Javascript
[02:16]完美世界DOTA2联赛PWL S3 集锦第三期
2020/12/21 DOTA
python常用web框架简单性能测试结果分享(包含django、flask、bottle、tornado)
2014/08/25 Python
Python函数中定义参数的四种方式
2014/11/30 Python
在Python中操作列表之List.pop()方法的使用
2015/05/21 Python
python制作爬虫并将抓取结果保存到excel中
2016/04/06 Python
Random 在 Python 中的使用方法
2018/08/09 Python
Python实现多属性排序的方法
2018/12/05 Python
python 弹窗提示警告框MessageBox的实例
2019/06/18 Python
python numpy存取文件的方式
2020/04/01 Python
Python爬虫库BeautifulSoup获取对象(标签)名,属性,内容,注释
2020/01/25 Python
Python unittest 自动识别并执行测试用例方式
2020/03/09 Python
Pycharm中如何关掉python console
2020/10/27 Python
html特殊符号示例 html特殊字符编码对照表
2014/01/14 HTML / CSS
美国五金商店:Ace Hardware
2018/03/27 全球购物
The North Face官方旗舰店:美国著名户外品牌
2020/09/28 全球购物
SQL Server 2000数据库的文件有哪些,分别进行描述
2013/03/30 面试题
长安大学毕业生自我鉴定
2014/01/17 职场文书
软件项目开发计划书
2014/05/01 职场文书
2014最新毕业证代领委托书
2014/09/26 职场文书
担保书怎么写 ?
2019/04/22 职场文书
Python爬虫之用Xpath获取关键标签实现自动评论盖楼抽奖(二)
2021/06/07 Python
Python 数据可视化之Matplotlib详解
2021/11/02 Python
keepalived + nginx 实现高可用方案
2022/12/24 Servers