Неожиданный результат PHP от float до типа int

Я пытаюсь преобразовать float в значение int в php:

var_dump((int)(39.3 * 100.0)); //Returns 3929 but should be 3930! var_dump((int)(39.2 * 100.0)); //Returns 3920 

Я могу использовать ceil, чтобы он работал, но может ли кто-нибудь объяснить это мне?

 var_dump((int)ceil(39.3 * 100.0)); //Returns 3930 

Это связано с тем, что числа, которые имеют конечное представление в базе 10, могут иметь или не иметь точного представления в представлении с плавающей запятой, которое использует PHP.

Видеть

 > php -r "echo var_dump (sprintf ('% .40F', 39.3 * 100.0));
 строка (45) "3929.9999999999995452526491135358810424804688"

Поскольку int всегда округляет число вниз, небольшая ошибка в представлении делает бросок вокруг него одним числом вниз, которое вы ожидали бы в противном случае.

Вместо этого подумайте об использовании round .

Это может быть поздно, но правильный способ сделать это выглядит следующим образом:

 (int) bcmul(39.3, 100.0); // 3930 (int) bcmul(39.2, 100.0); // 3920 

и для обработки цифр / вычислений для поплавков или всего, что связано с денежными транзакциями, вы никогда не должны использовать прямое умножение / деление + литье.

см. также:

http://php.net/manual/en/book.bc.php

обратите внимание: кастинг в моем ответе – это просто преобразовать String в Int (вам не нужно это делать)

Вы должны посмотреть на эту страницу: http://php.net/manual/en/language.types.float.php . Он описывает подводные камни, работающие с числами с плавающей запятой.

 // gives: int(3930) var_dump(intval((39.3 * 100.0) . '')); 

или, для использования с функцией:

 function floatToInteger ($fValue) { return (intval(($fValue + 0) . '')); } // gives: int(3930) var_dump(floatToInteger(39.3 * 100.0));