При получении результата умножения я получаю другой результат, чем при получении нормального числа. Ожидается ли такое поведение? Если да, то почему?
$val1 = 29;
$val2 = 0.29*100;
echo floor($val1); // prints 29
echo floor($val2); // prints 28
Это результат точности с плавающей точкой в 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.
Это часть странных ограничений 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/