php 浮点数比较方法

WBOY
Libérer: 2016-07-30 13:30:02
original
925 Les gens l'ont consulté

浮点数运算精度问题

首先看一个例子:

<code><span><span><?php </span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

var_dump((<span>$a</span>+<span>$b</span>)==<span>$c</span>);
var_dump((<span>$c</span>-<span>$b</span>)==<span>$a</span>);
<span>?></span></span></span></code>
Copier après la connexion

$a+$b==$c 返回true,正确
$c-$b==$a 返回false,错误

为什么会这样呢?
运算后,精度为20位时实际返回的内容如下:

<code><span><span><?php </span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

printf(<span>"%.20f"</span>, <span>$a</span>+<span>$b</span>); <span>// 1.00000000000000000000</span>
printf(<span>"%.20f"</span>, <span>$c</span>-<span>$b</span>); <span>// 0.09999999999999997780</span><span>?></span></span></span></code>
Copier après la connexion

$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方法处理后再比较
例子:

<code><span><span><?php </span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

var_dump((<span>$c</span>-<span>$b</span>)==<span>$a</span>);                   <span>// false</span>
var_dump(round((<span>$c</span>-<span>$b</span>),<span>1</span>)==round(<span>$a</span>,<span>1</span>)); <span>// true</span><span>?></span></span></span></code>
Copier après la connexion

2.使用高精度运算方法
首先进行运算时,使用高精度的运算方法,这样可以保证精度不丢失。

高精度运算的方法如下:
bcadd 将两个高精度数字相加
bccomp 比较两个高精度数字,返回-1,0,1
bcdiv 将两个高精度数字相除
bcmod 求高精度数字余数
bcmul 将两个高精度数字相乘
bcpow 求高精度数字乘方
bcpowmod 求高精度数字乘方求模
bcscale 配置默认小数点位数,相当于Linux bc中的”scale=”
bcsqrt 求高精度数字平方根
bcsub 将两个高精度数字相减

例子:

<code><span><span><?php </span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

var_dump((<span>$c</span>-<span>$b</span>)==<span>$a</span>);          <span>// false</span>
var_dump(bcsub(<span>$c</span>, <span>$b</span>, <span>1</span>)==<span>$a</span>); <span>// true</span><span>?></span></span></span></code>
Copier après la connexion

版权声明:本文为博主原创文章,未经博主允许不得转载。

以上就介绍了php 浮点数比较方法,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal