Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rounding integer to nearest multiple of another integer

Tags:

c++

I need to round integers to be the nearest multiple of another integer. Examples for results in the case of multiples of 100:

  • 36->0
  • 99->100
  • 123->100
  • 164->200

and so on.

I came up with the following code, that works, but feels "dirty":

int RoundToMultiple(int toRound, int multiple)
{
    return (toRound + (multiple / 2)) / multiple * multiple;
}

This counts on the truncating properties of integer division to make it work. Can I count on this code to be portable? Are there any compiler setups where this will fail to give me the desired result? If there are, how can I achieve the same results in a portable way?

If needed for a better answer, it can be assumed that multiples will be powers of 10 (including multiples of 1). Numbers can also be assumed to all be positive.

like image 210
Eyal K. Avatar asked May 22 '17 15:05

Eyal K.


1 Answers

Yes, you can count on this code to be portable. N4296 (which is the latest open draft of C++14) says in section 5.6 [expr.mul]:

For integral operands the / operator yields the algebraic quotient with any fractional part discarded. [Footnote: This is often called truncation towards zero]

This is not a new feature of the latest C++, it could be relied on in C89 too.

The only caveat, is that if toRound is negative, you need to subtract the offset.

An alternative approach is:

int RoundToMultiple(int toRound, int multiple)
{
    const auto ratio = static_cast<double>(toRound) / multiple;
    const auto iratio = std::lround(ratio);
    return iratio * multiple;
}

This avoid messy +/- offsets, but performance will be worse, and there are problems if toRound is so large that it can't be held precisely in a double. (OTOH, if this is for output, then I suspect multiple will be similarly large in this case, so you will be alright.)

like image 58
Martin Bonner supports Monica Avatar answered Sep 28 '22 07:09

Martin Bonner supports Monica