Ответ 1
Это точная проблема, присущая номерам с плавающей запятой в PHP и множеству других языков. Этот отчет об ошибке немного обсуждается в контексте кастинга как int:
http://bugs.php.net/bug.php?id=33731
Попробуйте round($val * 100)
.
Мальчик, этот действительно странный. Я ожидаю, что следующий код будет напечатан в 1990 году, но он печатает 1989 год!
$val = '$19.9';
$val = preg_replace('/[^\d.]/','',$val);
$val = intval($val * 100);
echo $val;
Почему это происходит?
Изменить: и этот код:
$val = '$19.9';
$val = preg_replace('/[^\d.]/','',$val);
echo $val . "<br>";
$val = $val * 100;
echo $val . "<br>";
$val = intval($val);
echo $val;
Печать
19.9
1990
1989
Почему intval(1990)
равно 1989
???
Это точная проблема, присущая номерам с плавающей запятой в PHP и множеству других языков. Этот отчет об ошибке немного обсуждается в контексте кастинга как int:
http://bugs.php.net/bug.php?id=33731
Попробуйте round($val * 100)
.
Обычный ответ на этот вопрос - читать Что должен знать каждый компьютерный ученый о арифметике с плавающей точкой.
Почему intval (1990) равен 1989???
Потому что вы не принимаете intval(1990)
. Вы принимаете intval($val * 100)
, где $val
- это число, близкое к нему, но немного меньшее, чем 19.9.
Прочитайте Руководство по плавающей запятой, чтобы понять, почему это так.
Как исправить это: никогда не используйте значения с плавающей запятой за деньги. В PHP вы должны использовать BCMath.
$val
- число с плавающей запятой - результат "19.9" * 100
. Номера с плавающей точкой не являются точными на 100% на любом языке (это по дизайну). Если вам нужна 100-процентная десятичная точность для значений доллара, вы должны использовать целые числа и выполнять все вычисления с использованием центов (например, "$19.90"
должно быть 1990
).