В версии ceil(pow(10, $precision) * $value)/pow(10, $precision);
терпит неудачу в некоторых случаях, например, round_up (2.22, 2) дает неверный 2.23, как указано here, поэтому я применил этот string solution for round_down() к нашей проблеме round_up(). Это результат (отрицательная точность не распространяется):
function round_up($value, $precision) {
$value = (float)$value;
$precision = (int)$precision;
if ($precision < 0) {
$precision = 0;
}
$decPointPosition = strpos($value, '.');
if ($decPointPosition === false) {
return $value;
}
$floorValue = (float)substr($value, 0, $decPointPosition + $precision + 1);
$followingDecimals = (int)substr($value, $decPointPosition + $precision + 1);
if ($followingDecimals) {
$ceilValue = $floorValue + pow(10, -$precision); // does this give always right result?
}
else {
$ceilValue = $floorValue;
}
return $ceilValue;
}
Я не знаю, что это пуленепробиваемое, но, по крайней мере, он удаляет упомянутые выше провал. Я не делал анализ с двоичным-десятичным-математическим анализом, но если $floorValue + pow(10, 0 - $precision)
работает всегда, как и ожидалось, тогда все должно быть в порядке. Если вы найдете какой-то неудачный случай, дайте мне знать - мы должны искать другое решение :)
Я думаю, что порядок работы перемешивается, вам нужно разделить, прежде потолке, а затем умножить, а не наоборот, нет? – nicolaskruchten
@njk: потолок (6244,64, -1) дает желаемый результат 6250. Обратите внимание, что точность в этом случае является отрицательной. –
Это вернет true: 'потолок (77.4, 2) === 77.41'. Функция сломана. – bzeaman