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如何透过ODBC来存取数据库
Oct 09 PHP
自己前几天写的无限分类类
Feb 14 PHP
PHP操作文件方法问答
Mar 16 PHP
phpMyAdmin2.11.6安装配置方法
Aug 24 PHP
PHP 简单日历实现代码
Oct 28 PHP
smarty模板嵌套之include与fetch性能测试
Dec 05 PHP
PHP提取字符串中的图片地址[正则表达式]
Nov 12 PHP
php微信高级接口群发 多客服
Jun 23 PHP
php指定长度分割字符串str_split函数用法示例
Jan 30 PHP
ThinkPHP中调用PHPExcel的实现代码
Apr 08 PHP
PHP完全二叉树定义与实现方法示例
Oct 09 PHP
PHP7.1实现的AES与RSA加密操作示例
Jun 15 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
在apache下限制每个虚拟主机的并发数!!!!
2006/10/09 PHP
简单的方法让你的后台登录更加安全(php中加session验证)
2012/08/22 PHP
php+ajax实现文章自动保存的方法
2014/12/30 PHP
PHP设计模式之观察者模式实例
2016/02/22 PHP
详解WordPress中添加友情链接的方法
2016/05/21 PHP
深入浅析安装PhpStorm并激活的步骤详解
2020/09/17 PHP
百度 popup.js 完美修正版非常的不错 脚本之家推荐
2009/04/17 Javascript
jquery ajax执行后台方法
2010/03/18 Javascript
jQuery中after的两种用法实例
2013/07/03 Javascript
javascript实现数字验证码的简单实例
2014/02/10 Javascript
JS实现OCX控件的事件响应示例
2014/09/17 Javascript
JS仿Windows开机启动Loading进度条的方法
2015/02/26 Javascript
js实现新年倒计时效果
2015/12/10 Javascript
基于Node.js的强大爬虫 能直接发布抓取的文章哦
2016/01/10 Javascript
探究Javascript模板引擎mustache.js使用方法
2016/01/26 Javascript
深入解析AngularJS框架中$scope的作用与生命周期
2016/03/05 Javascript
JS返回只包含数字类型的数组实例分析
2016/12/16 Javascript
js放到head中失效的原因与解决方法
2017/03/07 Javascript
JavaScript实现京东购物放大镜和选项卡效果的方法分析
2018/07/05 Javascript
JS+HTML实现的圆形可点击区域示例【3种方法】
2018/08/01 Javascript
微信小程序用户信息encryptedData详解
2018/08/24 Javascript
Javascript地址引用代码实例解析
2020/02/25 Javascript
[01:18]DOTA2超级联赛专访hanci ForLove淘汰感言曝光
2013/06/04 DOTA
Python爬虫抓取手机APP的传输数据
2016/01/22 Python
Python解析json之ValueError: Expecting property name enclosed in double quotes: line 1 column 2(char 1)
2017/07/06 Python
python 生成器协程运算实例
2017/09/04 Python
简单了解python关系(比较)运算符
2019/07/08 Python
Python numpy线性代数用法实例解析
2019/11/15 Python
keras tensorflow 实现在python下多进程运行
2020/02/06 Python
django 链接多个数据库 并使用原生sql实现
2020/03/28 Python
Python判断字符串是否为合法标示符操作
2020/09/03 Python
python 写一个水果忍者游戏
2021/01/13 Python
土木工程毕业生自荐信
2013/11/12 职场文书
图书馆志愿者活动总结
2014/06/27 职场文书
安全演讲稿开场白
2014/08/25 职场文书
公司周年庆典标语
2014/10/07 职场文书