Почему floor (0.99999999999999999) = 1 и floor (0.9999999999999999) = 0?

Функция пола в PHP ведет себя странно.
Для 16 десятичных значений это дает минимальное значение, но при увеличении 1 десятичного знака оно округляется.

$int = 0.99999999999999999;
echo floor($int); // returns 1

$int = 0.9999999999999999;
echo floor($int); // returns 0

$int = 0.99999999999999994;
echo floor($int); // returns 0
  1. Это где-то определено / объяснено, в какой момент оно дает «круглое» значение?
  2. Есть ли функция, которая дает 0 во всяком случае, сколько 9 в десятичных?

4

Решение

Это не floor что раунды, это математика с плавающей точкой, которая делает.

Эта строка:

echo 0.99999999999999999;

Печать 1 (демонстрация) так как 0.99999999999999999 является слишком точным, чтобы быть представленным (64-битным?) с плавающей точкой, поэтому берется самое близкое возможное значение, которое оказывается 1,
0.99999999999999994 также слишком точен, чтобы быть точно представленным, но здесь самое близкое представимое значение 0.9999999999999999,

  1. Это где-то определено / объяснено, в какой момент оно дает «круглое» значение?

Это сложно, но цифры округляются почти всегда.
Я полагаю, что нет определения «от того, когда значения будут приближены», но это математическое свойство, которое следует из определений в Стандарт IEEE 754 с плавающей запятой.
Чтобы быть в безопасности, просто предположите, что все приблизительно.

  1. Есть ли какая-либо функция, которая в любом случае дает 0, сколько 9 в десятичных числах?

Проблема в том, что для PHP 0.99999999999999999 буквально так же, как 1,
Они представлены одной и той же последовательностью битов, поэтому их невозможно различить.

Существует несколько решений для работы с десятичными числами с большей точностью, но для этого требуются серьезные изменения кода.
Возможно, вас интересует

Работа с большими числами в PHP

Обратите внимание, что в то время как вы можете получить произвольный Точность, вы никогда не получите бесконечный точность, поскольку это потребовало бы бесконечного количества памяти.

Также обратите внимание, что если вы на самом деле мы имея дело с бесконечной точностью, 0.999... (происходит вечно) будет действительно (как в, математически доказуемо) равно 1как подробно объясняется в эта статья в Википедии.

15

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

$float_14_digits = 0.99999999999999;
echo $float_14_digits; // prints 0.99999999999999
echo floor($float_14_digits); // prints 0

$float_15_digits = 0.999999999999999;
echo $float_15_digits; // prints 1
echo floor($float_15_digits); // prints 1
exit;

на моей машине разработки такое поведение происходит на цифре «15», а не «17», как у вас. PHP округляет последнюю цифру в плавающих числах. ваш floor() функция не имеет ничего общего с этим поведением

0

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