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 相关文章推荐
PHP5在Apache下的两种模式的安装
Sep 05 PHP
新版PHP极大的增强功能和性能
Oct 09 PHP
PHP读取MySQL数据代码
Jun 05 PHP
php socket方式提交的post详解
Jul 19 PHP
php 异常处理实现代码
Mar 10 PHP
php中用于检测一个地理IP地址是否可用的代码
Feb 19 PHP
PHP register_shutdown_function函数的深入解析
Jun 03 PHP
PHP验证码函数代码(简单实用)
Sep 29 PHP
PHP中的插件机制原理和实例
Jul 08 PHP
smarty模板引擎之分配数据类型
Mar 30 PHP
解决PHP里大量数据循环时内存耗尽的方法
Oct 10 PHP
PHP常见过waf webshell以及最简单的检测方法
May 21 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
德劲1107的电路分析与打磨
2021/03/02 无线电
Php部分常见问题总结
2006/10/09 PHP
在任意字符集下正常显示网页的方法二(续)
2007/04/01 PHP
php 地区分类排序算法
2013/07/01 PHP
Symfony2之session与cookie用法小结
2016/03/18 PHP
php swoole多进程/多线程用法示例【基于php7nts版】
2019/08/12 PHP
php让json_encode不自动转义斜杠“/”的方法
2020/04/27 PHP
自适应图片大小的弹出窗口
2006/07/27 Javascript
JS 自动安装exe程序
2008/11/30 Javascript
JQuery跨Iframe选择实现代码
2010/08/19 Javascript
原始XMLHttpRequest方法详情回顾
2013/11/28 Javascript
js实现C#的StringBuilder效果完整实例
2015/12/22 Javascript
AngularJS使用指令增强标准表单元素功能
2016/07/01 Javascript
jquery 判断selection range 是否在容器中的简单实例
2016/08/02 Javascript
关于TypeScript中import JSON的正确姿势详解
2017/07/25 Javascript
vue.js $refs和$emit 父子组件交互的方法
2017/12/20 Javascript
vue element-ui实现input输入框金额数字添加千分位
2019/12/29 Javascript
聊聊vue 中的v-on参数问题
2021/01/29 Vue.js
用于统计项目中代码总行数的Python脚本分享
2015/04/21 Python
Python简单实现enum功能的方法
2016/04/25 Python
NumPy.npy与pandas DataFrame的实例讲解
2018/07/09 Python
Pytorch 搭建分类回归神经网络并用GPU进行加速的例子
2020/01/09 Python
Django全局启用登陆验证login_required的方法
2020/06/02 Python
python实现磁盘日志清理的示例
2020/11/05 Python
HTML5 Blob对象的具体使用
2020/05/22 HTML / CSS
SQL Server 2000数据库的文件有哪些,分别进行描述
2013/03/30 面试题
大一自我鉴定范文
2013/10/04 职场文书
竞聘书怎么写,如何写?
2014/03/31 职场文书
中学优秀班主任事迹材料
2014/05/01 职场文书
迟到检讨书2000字(精选篇)
2014/10/07 职场文书
授权委托书
2015/01/28 职场文书
小学二年级班主任工作经验交流材料
2015/11/02 职场文书
优质服务心得体会(共4篇)
2016/01/22 职场文书
爱心捐款倡议书:点燃希望,传递温暖
2019/11/04 职场文书
MySQL完整性约束的定义与实例教程
2021/05/30 MySQL
Python3.10的一些新特性原理分析
2021/09/15 Python