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 编写安全的代码时容易犯的错误小结
May 20 PHP
php中++i 与 i++ 的区别
Aug 08 PHP
php对mongodb的扩展(初出茅庐)
Nov 11 PHP
PHP判断远程图片或文件是否存在的实现代码
Feb 20 PHP
php除数取整示例
Apr 24 PHP
30个php操作redis常用方法代码例子
Jul 05 PHP
PHP用反撇号执行外部命令
Apr 14 PHP
利用php输出不同的心形图案
Apr 22 PHP
PHP 数组遍历foreach语法结构及实例
Jun 13 PHP
php一个文件搞定微信jssdk配置
Dec 12 PHP
PHP设计模式之抽象工厂模式实例分析
Mar 25 PHP
PHP For循环字母A-Z当超过26个字母时输出AA,AB,AC
Feb 16 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
虫族 ZERG 概述
2020/03/14 星际争霸
一个php作的文本留言本的例子(五)
2006/10/09 PHP
PHP缓存机制Output Control详解
2014/07/14 PHP
微信接口生成带参数的二维码
2017/07/31 PHP
Javascript实例教程(19) 使用HoTMetal(3)
2006/12/23 Javascript
选择TreeView控件的树状数据节点的JS方法(jquery)
2010/02/06 Javascript
基于jQuery的倒计时插件代码
2011/05/07 Javascript
jquery formValidator插件ajax验证 内容不做任何修改再离开提示错误的bug解决方法
2013/01/04 Javascript
js中的eventType事件及其浏览器支持性介绍
2013/11/29 Javascript
Javascript Object 对象学习笔记
2014/12/17 Javascript
JavaScript判断变量是否为空的自定义函数分享
2015/01/31 Javascript
firefox浏览器用jquery.uploadify插件上传时报HTTP 302错误
2015/03/01 Javascript
react系列从零开始_简单谈谈react
2017/07/06 Javascript
JS 实现分页打印功能
2018/05/16 Javascript
linux 后台运行node服务指令方法
2018/05/23 Javascript
vue3.0 CLI - 2.4 - 新组件 Forms.vue 中学习表单
2018/09/14 Javascript
微信小程序实现底部导航
2018/11/05 Javascript
JavaScript之解构赋值的理解
2019/01/30 Javascript
Python批量查询域名是否被注册过
2017/06/21 Python
对pandas进行数据预处理的实例讲解
2018/04/20 Python
python实现12306登录并保存cookie的方法示例
2019/12/17 Python
python 决策树算法的实现
2020/10/09 Python
Python操作word文档插入图片和表格的实例演示
2020/10/25 Python
CSS3打造磨砂玻璃背景效果
2016/09/28 HTML / CSS
H5 meta小结(前端必看篇)
2016/08/24 HTML / CSS
英国汽车零件购物网站:GSF Car Parts
2019/05/23 全球购物
美国家庭鞋店:Shoe Sensation
2019/09/27 全球购物
俄罗斯药房连锁店:ASNA
2020/06/20 全球购物
应用电子技术专业个人求职信
2013/09/21 职场文书
办理护照介绍信
2014/01/16 职场文书
幼儿园中班教学反思
2014/02/10 职场文书
标准化管理实施方案
2014/02/25 职场文书
旺仔牛奶广告词
2014/03/20 职场文书
教你使用Python pypinyin库实现汉字转拼音
2021/05/27 Python
MySQL不使用order by实现排名的三种思路总结
2021/06/02 MySQL
Python 语言实现六大查找算法
2021/06/30 Python