Мальчик, это действительно странно. Я ожидаю, что следующий код напечатает 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
).