PHP floor() 奇怪的行为

PHP floor() weird behaviour

当对乘法结果进行取整时,我得到的结果与对普通数字进行取整时的结果不同。这种行为是预期的吗?如果是,为什么?

$val1 = 29;
$val2 = 0.29*100;

echo floor($val1); // prints 29
echo floor($val2); // prints 28

它是 PHP 怪异精度的一部分。看机器是正常的。

Floating point numbers have limited precision. Although it depends on the system, PHP typically uses the IEEE 754 double precision format, which will give a maximum relative error due to rounding in the order of 1.11e-16. Non elementary arithmetic operations may give larger errors, and, of course, error propagation must be considered when several operations are compounded.

另外,有理数可以精确表示为 以 10 为基数的浮点数,如 0.1 或 0.7,没有 精确表示为以 2 为基数的浮点数,即 内部使用,不管尾数的大小。因此,他们 如果没有 精度损失小。这可能会导致令人困惑的结果:对于 例如,floor((0.1+0.7)*10) 通常会 return 7 而不是 预期为 8,因为内部表示类似于 7.999999999999991118 ....

所以永远不要相信浮点数结果的最后一位,也不要 直接比较浮点数是否相等。如果更高 精度是必要的,任意精度数学函数和 gmp 功能可用。

http://techiedan.com/2013/10/11/php-floor-function-float-value/

这是 PHP 中浮点精度的结果,在您的示例中:

gettype($val1); returns integer

gettype($val2); returns double

将其与 php.net 上的此警告相结合:

Additionally, rational numbers that are exactly representable as floating point numbers in base 10, like 0.1 or 0.7, do not have an exact representation as floating point numbers in base 2, which is used internally, no matter the size of the mantissa. Hence, they cannot be converted into their internal binary counterparts without a small loss of precision. This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8, since the internal representation will be something like 7.9999999999999991118....

取自http://php.net/manual/en/language.types.float.php

而且我们可以看到为什么您的地板从 28.9999999999 等下降到 28,而不是整数 29 到 29。