Почему `intval (19.9 * 100)` равно `1989`?

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