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代码收集表单内容并写入文件的代码
Jan 29 PHP
使用Discuz关键词服务器实现PHP中文分词
Mar 11 PHP
ThinkPHP自动填充实现无限级分类的方法
Aug 22 PHP
ThinkPHP模板输出display用法分析
Nov 26 PHP
PHP程序员必须清楚的问题汇总
Dec 18 PHP
php验证码生成代码
Nov 11 PHP
PHP封装返回Ajax字符串和JSON数组的方法
Feb 17 PHP
PHP实现的mysql读写分离操作示例
May 22 PHP
Laravel 验证码认证学习记录小结
Dec 20 PHP
Yii框架多语言站点配置方法分析【中文/英文切换站点】
Apr 07 PHP
php使用自带dom扩展进行元素匹配的原理解析
May 29 PHP
Nginx+php配置文件及原理解析
Dec 09 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
常见的四种POST 提交数据方式(小总结)
2015/10/08 PHP
实例分析基于PHP微信网页获取用户信息
2017/11/24 PHP
JavaScript作用域与作用域链深入解析
2013/12/06 Javascript
node.js中的path.delimiter方法使用说明
2014/12/09 Javascript
JavaScript使用cookie实现记住账号密码功能
2015/04/27 Javascript
js实现带圆角的两级导航菜单效果代码
2015/08/24 Javascript
轻松实现js图片预览功能
2016/01/18 Javascript
一种Javascript解释ajax返回的json的好方法(推荐)
2016/06/02 Javascript
全面解析Bootstrap中tab(选项卡)的使用方法
2016/06/06 Javascript
JS+CSS3模拟溢出滚动效果
2016/08/12 Javascript
JavaScript生成验证码并实现验证功能
2016/09/24 Javascript
Mac下通过brew安装指定版本的nodejs教程
2018/05/17 NodeJs
Vue 理解之白话 getter/setter详解
2019/04/16 Javascript
Vue源码探究之虚拟节点的实现
2019/04/17 Javascript
vue循环数组改变点击文字的颜色
2019/10/14 Javascript
使用webpack搭建vue环境的教程详解
2019/12/31 Javascript
原生js实现的观察者和订阅者模式简单示例
2020/04/18 Javascript
Python图像灰度变换及图像数组操作
2016/01/27 Python
Django实现组合搜索的方法示例
2018/01/23 Python
python实现12306抢票及自动邮件发送提醒付款功能
2018/03/08 Python
Python使用numpy产生正态分布随机数的向量或矩阵操作示例
2018/08/22 Python
利用Pycharm断点调试Python程序的方法
2018/11/29 Python
使用OpCode绕过Python沙箱的方法详解
2019/09/03 Python
pytorch 自定义参数不更新方式
2020/01/06 Python
使用Python pip怎么升级pip
2020/08/11 Python
关于django python manage.py startapp 应用名出错异常原因解析
2020/12/15 Python
奢华的意大利皮革手袋:Bene Handbags
2019/10/29 全球购物
行政助理岗位职责范文
2013/12/03 职场文书
幼儿园国庆节活动方案
2014/02/01 职场文书
道德之星事迹材料
2014/05/03 职场文书
伊琍体标语
2014/06/25 职场文书
行政管理专业求职信
2014/07/06 职场文书
2014广电局实施党的群众路线教育实践活动方案思想汇报
2014/09/22 职场文书
高二学年自我鉴定范文(2篇)
2014/09/26 职场文书
三年级学生评语大全
2014/12/26 职场文书
计划生育工作总结2015
2015/04/03 职场文书