0

I tried this function

function roundUpToAny($n,$x=5) {
    return (round($n)%$x === 0) ? round($n) : round(($n+$x/2)/$x)*$x;
}

echo roundUpToAny(4.52); // This show 5 instead of 4.55

echo roundUpToAny(5.1); // This show 5 instead of 5.10

How can i created such function

Prabhakaran
  • 3,900
  • 15
  • 46
  • 113
  • This question is about rounding - it may be useful: [4483540/php-show-a-number-to-2-decimal-places](http://stackoverflow.com/questions/4483540/php-show-a-number-to-2-decimal-places) – Ryan Vincent May 24 '14 at 02:16
  • Multiply by two, round to 1 sf, divide by two. Does it have to work for negative numbers? – Floris May 24 '14 at 02:17
  • @Floris as of now I will not allow negative numbers – Prabhakaran May 24 '14 at 02:23
  • @RyanVincent I tried the one in the link provied, If my input is 4.21 its giving 4.21 as output instead of 4.25 – Prabhakaran May 24 '14 at 02:25

1 Answers1

2

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.

Floris
  • 45,857
  • 6
  • 70
  • 122