ceil()函数(php)的奇怪工作方式


Strange working of ceil() function (php)

代码:

echo (40 * (10 / 100 + 1)); //44
echo (50 * (10 / 100 + 1)); //55
echo ceil(40 * ((10 / 100) + 1)); //44
echo ceil(50 * ((10 / 100) + 1)); //56 (!)

我认为,"56"是由于浮点数(55.0000000001 => 56),但我不明白为什么对于"40"的结果是"44",而不是"45"

55实际上不是55。您可以很容易地验证:

<?php
$x = (40 * (10 / 100 + 1)); // 44
$y = (50 * (10 / 100 + 1)); // 55
echo '$x == 44: ' . ($x == 44 ? 'True' : 'False') . "'n";
echo '$y == 55: ' . ($y == 55 ? 'True' : 'False') . "'n";
echo '$y > 55: ' . ($y > 55 ? 'True' : 'False') . "'n";
echo $y - 55;

收益率:

$x == 44: True
$y == 55: False
$y > 55: True
7.105427357601E-15

正如你所看到的,差异很小(7.1 * 10^-15),但仍然使其大于55,因此ceil将其四舍五入。

你只看到55的原因是因为回显它会将浮点数转换为字符串:

字符串转换在需要字符串的表达式范围内自动完成。当使用echo或print函数时,或者将变量与字符串进行比较时,就会发生这种情况。

对于这种转换,标准截断行为将在某个点切断数字。通过"precision"配置参数配置,默认值为"14"。您可以通过使用自定义精度的sprintf来避免这种行为:

echo sprintf('%.50f', $y);
// 55.00000000000000710542735760100185871124267578125000

我们需要注意浮点精度http://php.net/manual/en/language.types.float.php

可精确表示为浮点数的有理数以10为基数的数字,比如0.1或0.7,没有精确数字表示为以2为基数的浮点数在内部,不管尾翼的大小。因此,它们不可能是转换成它们内部对应的二进制而没有一点损失的精度。这可能会导致令人困惑的结果:例如,Floor((0.1+0.7)*10)通常会返回7而不是预期的8,因为内部表示是这样的

7.9999999999999991118……

这是问题的答案为什么我的数字不加起来? http://floating-point-gui.de/。简洁地解释为什么你会得到意想不到的结果