views:

682

answers:

4

Given integer values x and y, C and C++ both return as the quotient q = x/y the floor of the floating point equivalent. I'm interestd in a method of returning the ceiling instead. For example, ceil(10/5) = 2 and ceil(11/5) = 3.

The obvious approach involves something like:

q = x / y;
if (q * y < x) ++q;

This requires an extra comparison and multiplication; and other methods I've seen (used in fact) involve casting as a float or double. Is there a more direct method that avoids the additional multiplication (or a second division) and branch, and that also avoids casting as a floating point number?

+21  A: 

To round up ...

q = (x + y - 1) / y;
Sparky
Yeah, that'll work. Thanks.
andand
Note: this will only work for positive numbers.
bitc
I would unit-test this just in case.
Hamish Grubijan
@bitc: For negative numbers, I believe C99 specifies round-to-zero, so `x/y` is the ceiling of the division. C90 didn't specify how to round, and I don't think the current C++ standard does either.
David Thornley
See Eric Lippert's post: http://stackoverflow.com/questions/921180/c-round-up/926806#926806
Mashmagar
Note: This might overflow. q = ((long long)x + y - 1) / y will not. My code is slower though, so if you know that your numbers will not overflow, you should use Sparky's version.
Jørgen Fogh
@David Thornley: iirc, that only applies to conversions from floating point to int. In the above code negative numbers cause havoc: q = (11 + (-5) - 1) / (-5);
bitc
God, one of the most upvoted posts I have ever seen outside of community wiki posts!
Matthieu M.
@bitc: I believe David's point was that you would not use the above calculation if the result is negative - you would just use `q = x / y;`
caf
+4  A: 

You could use the div function in cstdlib to get the quotient & remainder in a single call and then handle the ceiling separately, like in the below

#include <cstdlib>
#include <iostream>

int div_ceil(int numerator, int denominator)
{
        std::div_t res = std::div(numerator, denominator);
        return res.rem ? (res.quot + 1) : res.quot;
}

int main(int, const char**)
{
        std::cout << "10 / 5 = " << div_ceil(10, 5) << std::endl;
        std::cout << "11 / 5 = " << div_ceil(11, 5) << std::endl;

        return 0;
}
Nathan Ernst
As an interesting case of the double bang, you could also `return res.quot + !!res.rem;` :)
280Z28
+7  A: 

Sparky's answer is one standard way to solve this problem, but as I also wrote in my comment, you run the risk of overflows. This can be solved by using a wider type, but what if you want to divide long longs?

Nathan Ernst's answer provides one solution, but it involves a function call, a variable declaration and a conditional, which makes it no shorter than the OPs code and probably even slower, because it is harder to optimize.

My solution is this:

q = (x % y) ? x / y + 1 : x / y);

It will be slightly faster than the OPs code, because the modulo and the division is performed using the same instruction on the processor, because the compiler can see that they are equivalent. At least gcc 4.4.1 performs this optimization with -O2 flag on x86.

In theory the compiler might inline the function call in Nathan Ernst's code and emit the same thing, but gcc didn't do that when I tested it. This might be because it would tie the compiled code to a single version of the standard library.

As a final note, none of this matters on a modern machine, except if you are in an extremely tight loop and all your data is in registers or the L1-cache. Otherwise all of these solutions will be equally fast, except for possibly Nathan Ernst's, which might be significantly slower if the function has to fetched from main memory.

Jørgen Fogh
+1 Nice, in-depth answer.
Kevin Little
There was an easier way to fix overflow, simply reduce y/y: `q = (x > 0)? 1 + (x - 1)/y: (x / y);`
Ben Voigt
+3  A: 

How about this? (requires y non-negative, so don't use this in the rare case where y is a variable with no non-negativity guarantee)

q = (x > 0)? 1 + (x - 1)/y: (x / y);

I reduced y/y to one, eliminating the term x + y - 1 and with it any chance of overflow.

I avoid x - 1 wrapping around when x is an unsigned type and contains zero.

For signed x, negative and zero still combine into a single case.

Probably not a huge benefit on a modern general-purpose CPU, but this would be far faster in an embedded system than any of the other correct answers.

Ben Voigt
+1: Nice answer! It seems so obvious now. ;-)
Jørgen Fogh