Почему-то PHP считает, что в моем скрипте 3,57 + 0,01 равно 3,5799999999999996.
Я проверил около 10 других подобных сумм (например, 10,51 + 0,01), а затем PHP дал мне правильный ответ (10,52 в последнем случае). Итак, как ни странно, эта ошибка возникает только с этими конкретными поплавками.
Код: (упрощен для удобства чтения)
$users = array();
$IDs = [1,2,3];
foreach($IDs as $ID)
{
$user = (object) array();
$user->ID = $ID;
$users[] = $user;
}
$initialAmount = 3.57;
$chosenIDs = [1,3];
foreach ($users as $key => $value)
{
$users[$key]->amount = $initialAmount;
if (in_array($key, $chosenIDs))
{
//the following returns 3.5799999999999996
$users[$key]->amount = $users[$key]->amount + 0.01;
//even if I do it like the following, it returns the wrong answer
$users[$key]->amount = 3.57 + 0.01; //according to PHP equals 3.5799999999999996
//the following actually gives the correct answer though
//$users[$key]->amount = ($users[$key]->amount * 100 + 1) / 100;
}
}
Это какая-то странная ошибка в моей конфигурации или что здесь происходит?
Это не ошибка, а правильный ответ. Это присуще использованию поплавков, у них ограниченная точность. См .: php.net/manual/en/language.types.float.php
А, ладно, но 3,57 + 0,01 на самом деле не такая точная и, прежде всего, не такая уж сложная сумма, если честно;). Это действительно нормально, что PHP не может решить эту проблему правильно? Странно то, что это происходит только внутри этой функции. Возможно, это связано с какой-то нехваткой хранилища переменных? Или я предлагаю сейчас что-то совершенно глупое?
Ах, теперь я лучше прочитал связанный документ, и теперь я его лучше понимаю. Так что мой предыдущий комментарий был действительно глупым, ха-ха. Спасибо






Как уже упоминалось, это проблема с математикой с плавающей запятой, а не с php.
http://php.net/manual/en/language.types.float.php
Вы можете избежать этого, используя расширение BC Math при работе с числами, где ошибки с плавающей точкой могут стать проблемой. Поддерживает произвольную точность.
Типы переменных double и float имеют ограниченную точность