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写的小东西
Dec 06 PHP
PHP foreach循环使用详解与实例代码
May 08 PHP
Android ProgressBar进度条和ProgressDialog进度框的展示DEMO
Jun 19 PHP
本地机apache配置基于域名的虚拟主机详解
Aug 10 PHP
php class类的用法详细总结
Oct 17 PHP
使用php测试硬盘写入速度示例
Jan 27 PHP
PHP 使用memcached简单示例分享
Mar 05 PHP
php查询whois信息的方法
Jun 08 PHP
详解 PHP加密解密字符串函数附源码下载
Dec 18 PHP
老生常谈PHP面向对象之解释器模式
May 17 PHP
php封装db类连接sqlite3数据库的方法实例
Dec 19 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实现微信小程序用户授权的工具类示例
2019/03/05 PHP
Yii框架学习笔记之session与cookie简单操作示例
2019/04/30 PHP
Laravel5.3+框架定义API路径取消CSRF保护方法详解
2020/04/06 PHP
jQuery操作DOM之获取表单控件的值
2015/01/23 Javascript
jQuery仿Flash上下翻动的中英文导航菜单实例
2015/03/10 Javascript
javascript返回顶部的按钮实现方法
2016/01/09 Javascript
NodeJS实现阿里大鱼短信通知发送
2016/01/17 NodeJs
动态加载js文件简单示例
2016/04/21 Javascript
js设置文字颜色的方法示例
2016/12/30 Javascript
vue安装和使用scss及sass与scss的区别详解
2018/10/15 Javascript
Vue中使用方法、计算属性或观察者的方法实例详解
2018/10/31 Javascript
详解关于html,css,js三者的加载顺序问题
2019/04/10 Javascript
探索浏览器页面关闭window.close()的使用详解
2020/08/21 Javascript
[01:17]炒鸡美酒第四天TA暴走
2018/06/05 DOTA
[01:15]PWL S2开团时刻第二期——他们杀 我就白给
2020/11/25 DOTA
深入理解Python爬虫代理池服务
2018/02/28 Python
python 将md5转为16字节的方法
2018/05/29 Python
Python给定一个句子倒序输出单词以及字母的方法
2018/12/20 Python
Python List cmp()知识点总结
2019/02/18 Python
Python + Requests + Unittest接口自动化测试实例分析
2019/12/12 Python
python绘制雪景图
2019/12/16 Python
Python3 获取文件属性的方式(时间、大小等)
2020/03/12 Python
python3 自动打印出最新版本执行的mysql2redis实例
2020/04/09 Python
Python实现aes加密解密多种方法解析
2020/05/15 Python
pycharm激活方法到2099年(激活流程)
2020/09/22 Python
python函数超时自动退出的实操方法
2020/12/28 Python
Wiggle美国:英国骑行、跑步、游泳、铁人三项商店
2018/10/27 全球购物
新奥尔良珠宝:Mignon Faget
2020/11/23 全球购物
以太网Ethernet IEEE802.3
2013/08/05 面试题
会计电算化大学生职业规划书
2014/02/05 职场文书
工作简历自我评价
2015/03/11 职场文书
2016年习主席讲话学习心得体会
2016/01/20 职场文书
2016银行求职自荐信
2016/01/28 职场文书
教师师德承诺书2016
2016/03/25 职场文书
导游词之舟山普陀山
2019/11/06 职场文书
Python将CSV文件转化为HTML文件的操作方法
2021/06/30 Python