views:

158

answers:

2

I have the following function that rounds a number to the nearest number ending with the digits of $nearest, and I was wondering if there is a more elegant way of doing the same.

/**
 * Rounds the number to the nearest digit(s).
 *
 * @param int $number
 * @param int $nearest
 * @return int
 */

function roundNearest($number, $nearest, $type = null)
{
    $result = abs(intval($number));
    $nearest = abs(intval($nearest));

    if ($result <= $nearest)
    {
     $result = $nearest;
    }

    else
    {
     $ceil = $nearest - substr($result, strlen($result) - strlen($nearest));
     $floor = $nearest - substr($result, strlen($result) - strlen($nearest)) - pow(10, strlen($nearest));

     switch ($type)
     {
      case 'ceil':
       $result += $ceil;
      break;

      case 'floor':
       $result += $floor;
      break;

      default:
       $result += (abs($ceil) <= abs($floor)) ? $ceil : $floor;
      break;
     }
    }

    if ($number < 0)
    {
     $result *= -1;
    }

    return $result;
}

Some examples:

roundNearest(86, 9); // 89
roundNearest(97, 9); // 99
roundNearest(97, 9, 'floor'); // 89

Thanks in advance!

PS: This question is not about rounding to the nearest multiple.

+2  A: 

I think this should work, and it's more elegant to me, at least:

function roundNearest($number, $nearest, $type = null)
{
  if($number < 0)
    return -roundNearest(-$number, $nearest, $type);

  $nearest = abs($nearest);
  if($number < $nearest)
    return $nearest;

  $len = strlen($nearest);
  $pow = pow(10, $len);
  $diff = $pow - $nearest;

  if($type == 'ciel')
    $adj = 0.5;
  else if($type == 'floor')
    $adj = -0.5;
  else
    $adj = 0;

  return round(($number + $diff)/$pow + $adj)*$pow - $diff;
}

Edit: Added what I think you want from negative inputs.

Kip
There's too much repetition for it to be elegant.
Reinis I.
@Reinis I.: OK I made it a little eleganter.
Kip
A: 

This works for me:

function roundToDigits($num, $suffix, $type = 'floor') {
    $pow = pow(10, strlen($suffix));
    return $type(($num - $suffix) / $pow) * $pow + $suffix; 
};

$type should be either "ceil", "floor", or "round"

nickf
Always rounds numbers down, returns `79`, `89` and `89` for the examples provided in my question.
Alix Axel
Did you change the `$type` parameter?`roundToDigits(94,9,'floor')==89`, `roundToDigits(94,9,'ceil')==99`, `roundToDigits(94,9,'round')==99`
nickf