отладка — PHP floor () странное поведение

При получении результата умножения я получаю другой результат, чем при получении нормального числа. Ожидается ли такое поведение? Если да, то почему?

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

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

0

Решение

Это результат точности с плавающей точкой в ​​PHP, в вашем примере:

gettype($val1); возвращается integer

а также

gettype($val2); возвращается double

Объедините это с этим предупреждением на php.net:

Кроме того, рациональные числа, которые точно представимы как
Числа с плавающей запятой в базе 10, такие как 0,1 или 0,7, не имеют
точное представление в виде чисел с плавающей точкой в ​​базе 2, которая
используется внутри, независимо от размера мантиссы. Следовательно, они
не могут быть преобразованы в их внутренние двоичные аналоги без
небольшая потеря точности. Это может привести к запутанным результатам: для
Например, floor ((0.1 + 0.7) * 10) обычно возвращает 7 вместо
ожидается 8, так как внутреннее представление будет что-то вроде
+7,9999999999999991118 ….

взято из http://php.net/manual/en/language.types.float.php

И мы можем видеть, почему ваш пол принимает 28.9999999999 и т. Д. До 28, а не от 29 до 29.

4

Другие решения

Это часть странных ограничений PHP. Это нормально в зависимости от машины.

Числа с плавающей точкой имеют ограниченную точность. Хотя это зависит от системы, PHP обычно использует двойную точность IEEE 754
формат, который даст максимальную относительную ошибку из-за округления в
порядок 1.11e-16. Не элементарные арифметические операции могут дать
большие ошибки, и, конечно же, следует учитывать распространение ошибок
когда несколько операций составлены.

Кроме того, рациональные числа, которые точно представимы как
Числа с плавающей запятой в базе 10, такие как 0,1 или 0,7, не имеют
точное представление в виде чисел с плавающей точкой в ​​базе 2, которая
используется внутри, независимо от размера мантиссы. Следовательно, они
не могут быть преобразованы в их внутренние двоичные аналоги без
небольшая потеря точности. Это может привести к запутанным результатам: для
Например, floor ((0.1 + 0.7) * 10) обычно возвращает 7 вместо
ожидается 8, так как внутреннее представление будет что-то вроде
7,9999999999999991118 ….

Поэтому никогда не доверяйте результатам с плавающей точкой до последней цифры и не
сравнить числа с плавающей запятой непосредственно на равенство. Если выше
нужна точность, математические функции произвольной точности и gmp
функции доступны.

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

3

По вопросам рекламы [email protected]