浮点数运算的灵异问题

本来准备看下程序执行的耗时,结果发现一个灵异问题,代码如下:


$x = microtime(true);

/*中间代码省略*/

$y = microtime(true);

echo ($y-$x) . "\n";

结果输出为:

2.8610229492188E-6

应该是会返回秒数的,怎么会变成上面这种呢?
翻了下PHP手册,里面提到这么一句。

如果给出了 get_as_float 参数并且其值等价于 TRUE, microtime 将返回一个浮点数。

百思不得其解,问了下朋友,后来发现是浮点数运算的问题。

再看一个例子,代码如下:

$a = 0.1;
$b = 0.7;
var_dump(($a + $b) == 0.8);

结果输出为:

bool(false)

再来一个例子,代码如下:

$a = 0.1+0.7;
$b = 0.8;
printf("%0.20f", $a);
echo '
'; printf("%0.20f", $b);

结果输出为:

0.79999999999999993339
0.80000000000000004441

显然在这里,实际上作为浮点型数据,其精度已经损失了一部分,达不到完全精确。所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。需要说明的是,这不是PHP的问题,而是计算机内部处理浮点数的问题!在 C、JAVA 等语言中也会遇到同样的问题。

所以要比较两个浮点数,需要将其控制在我们需要的精度范围内再行比较,因此使用 bcadd() 函数来对浮点数想加并进行精度转换(为字符串):

var_dump(bcadd(0.1,0.7,1) == 0.8);

结果输出为:

bool(true)

标签: none

添加新评论