这里有新鲜出炉的 PHP 教程,程序狗速度看过来!
PHP(外文名: Hypertext Preprocessor,中文名:"超文本预处理器")是一种通用开源脚本语言。语法吸收了 C 语言、Java 和 Perl 的特点,入门门槛较低,易于学习,使用广泛,主要适用于 web 开发领域。PHP 的文件后缀名为 php。
本篇文章主要介绍了 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
- ?>
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持 PHPERZ!
来源: http://www.phperz.com/article/17/0810/339937.html