浮点数运算的灵异问题
本来准备看下程序执行的耗时,结果发现一个灵异问题,代码如下:
$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)