I think the following function does what you want:
function roundUpToAny($n, $x=5, $sf=2) {
$scale = pow(10,$sf);
return number_format(round(ceil($n*$scale / $x), $sf) * $x / $scale, $sf);
}
The first argument is the number to be converted, the second is the "rounding factor" (multiples of $x
- you asked for 5
in the title of the question), the third is the number of figures after the decimal point.
Test:
echo roundUpToAny(1.23, 5, 2) ."\n";
echo roundUpToAny(4.54, 5, 2) ."\n";
echo roundUpToAny(5.101, 5, 3) ."\n";
echo roundUpToAny(1.19, 5, 3) ."\n";
Result:
1.25
4.55
5.105
1.190
UPDATE
You pointed out in a follow-up that the above code fails for inputs of 1.1
and 2.2
. The reason for this is the fact that these numbers are not exactly representable in double precision (strange though this may sound). The following code compensates for this, by creating an intermediate value that is rounded to be an integer (and therefore can be represented exactly):
function roundUpToAny($n, $x=5, $sf=2) {
$scale = pow(10,$sf);
$temp = round($n * $scale, $sf); // get rid of small rounding errors
return number_format(round(ceil($temp / $x), $sf) * $x / $scale, $sf);
}
Testing:
echo roundUpToAny(1.1, 5, 2) ."\n";
Result:
1.10
As expected.