因为浮点数并不仅存在计算上的缺陷,有时其表示方法也
存在缺陷,这就是本例的情况。
实际上你得到的并不是0.1、0.2等数值,这很容易验证:
$start = 0;
$stop = 1;
$step = ($stop - $start)/10;
$i = $start + $step;
while ($i < $stop) {
print(number_format($i, 32) . "<br />");
$i += $step;
}
这里唯一的区别就是将
echo
替换为
number_format
调用。但结果却截然不同:
0.10000000000000000555111512312578
0.20000000000000001110223024625157
0.30000000000000004440892098500626
0.40000000000000002220446049250313
0.50000000000000000000000000000000
0.59999999999999997779553950749687
0.69999999999999995559107901499374
0.79999999999999993338661852249061
0.89999999999999991118215802998748
0.99999999999999988897769753748435
看到了吗?实际上只有一次是0.5 - 因为这个数字可以存储在浮点容器中。所有其他的都只是近似值。
如何解决这个问题?一个激进的方法是在类似的情况下使用整数而不是浮点数。很容易注意到,如果你这样做...
$start = 0;
$stop = 10;
$step = (int)(($stop - $start) / 10);
$i = $start + $step;
while ($i < $stop) {
print(number_format($i, 32) . "<br />");
$i += $step;
}
"...它应该可以正常工作:
或者,您可以使用number_format
将浮点数转换为某个字符串,然后将此字符串与预格式化的浮点数进行比较。像这样:"
$start = 0;
$stop = 1;
$step = ($stop - $start) / 10;
$i = $start + $step;
while (number_format($i, 1) !== number_format($stop, 1)) {
print(number_format($i, 32) . "\n");
$i += $step;
}
$i
恰好等于1。然而,你不能直接比较浮点数是否相等。 - Jon