Попробуйте это как быстрое решение:
$price_int = intval(floor($price_corrected + 0.5));
Проблема, с которой вы столкнулись, не является ошибкой PHP, все языки программирования, использующие действительные числа с арифметикой с плавающей запятой, имеют аналогичные проблемы.
Общее эмпирическое правило для денежных расчетов — никогда не использовать числа с плавающей запятой (ни в базе данных, ни в вашем скрипте). Вы можете избежать всевозможных проблем, всегда храня центы вместо долларов. Центы — это целые числа, и вы можете свободно их складывать и умножать на другие целые числа. Всякий раз, когда вы показываете номер, убедитесь, что вы вставляете точку перед двумя последними цифрами.
Причина, по которой вы получаете 114 вместо 115, заключается в том, что floor
округляется вниз до ближайшего целого числа, таким образом, пол (114,999999999) становится 114. Более интересный вопрос заключается в том, почему 1,15 * 100 равно 114,999999999, а не 115. Причина этого в том, что 1,15 — это не совсем 115/100, но это немного меньше, поэтому, если вы умножите на 100, вы получите число чуть меньше 115.
Вот более подробное объяснение того, что делает echo 1.15 * 100;
:
- Он анализирует 1.15 в двоичное число с плавающей запятой. Это включает в себя округление, бывает, что округление происходит немного вниз, чтобы получить двоичное число с плавающей запятой, ближайшее к 1,15. Причина, по которой вы не можете получить точное число (без ошибки округления), заключается в том, что 1,15 имеет бесконечное количество цифр в основании 2.
- Он анализирует 100 в двоичное число с плавающей запятой. Это связано с округлением, но поскольку 100 — небольшое целое число, ошибка округления равна нулю.
- Он вычисляет произведение двух предыдущих чисел. Это также включает в себя небольшое округление, чтобы найти ближайшее двоичное число с плавающей запятой. Ошибка округления оказывается равной нулю в этой операции.
- Он преобразует двоичное число с плавающей запятой в десятичное число с основанием 10 с точкой и печатает это представление. Это также включает в себя небольшое округление.
Причина, по которой PHP выводит удивительное число Corrected price = float(115)
(вместо 114.999...), заключается в том, что var_dump
выводит не точное число (!), а число, округленное до n - 2
(или n - 1
) цифр, где n цифр — это точность. расчета. Вы можете легко убедиться в этом:
echo 1.15 * 100; # this prints 115
printf("%.30f", 1.15 * 100); # you 114.999....
echo 1.15 * 100 == 115.0 ? "same" : "different"; # this prints `different'
echo 1.15 * 100 < 115.0 ? "less" : "not-less"; # this prints `less'
Если вы печатаете числа с плавающей запятой, помните: вы не всегда видите все цифры при печати числа с плавающей запятой.
См. также большое предупреждение в начале документации PHP float.
person
pts
schedule
01.05.2009