php 浮点数比较方法详解

yipeiwu_com7年前PHP代码库

浮点数运算精度问题

首先看一个例子:

<?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
?>

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持【宜配屋www.yipeiwu.com】!

相关文章

php str_getcsv把字符串解析为数组的实现方法

php根据定界符把字符串解析为数组一般使用explode方法实现 例如:使用”,”为定界符解析字符串为数组 <?php $str = '1,2,3'; $arr = e...

php session和cookie使用说明

1. PHP的COOKIE cookie 是一种在远程浏览器端储存数据并以此来跟踪和识别用户的机制。PHP在http协议的头信息里发送cookie, 因此setcookie() 函数必须...

phpinfo的知识点总结

phpinfo是一个运行指令,为显示php服务器的配置信息。 phpinfo-输出大量PHP信息 bool phpinfo() 输出 PHP 当前状态的大量信息,包含了 PHP 编...

php使用CURL伪造IP和来源实例详解

本文实例讲述了php使用CURL伪造IP和来源的方法。分享给大家供大家参考。具体分析如下: 伪造IP来源对于php来说是很简单的一件事情,我们只要利用了php的curl即可实现伪造IP来...

php之CodeIgniter学习笔记

在使用数据库之前,我们最好将数据库进行自动连接:config/autoload.php自动加载 $autoload['libraries'] = array('database');一些...