As version ceil(pow(10, $precision) * $value) / pow(10, $precision);
fails in some cases, e.g. round_up(2.22, 2) gives incorrect 2.23 as mentioned here, so I have adapted this string solution for round_down() to our round_up() problem. This is the result (a negative precision is not covered):
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;
}
I don't know it is bulletproof, but at least it removes the above mentioned fail. I have done no binary-to-decimal-math-analysis but if $floorValue + pow(10, 0 - $precision)
works
always as expected then it should be ok. If you will find some failing case let me know - we should look for another solution :)