It's very common to need to divide integers but get the result rounded up rather than down. For a while now, I've been using the following function for that mini-idiom:
template <typename S, typename T>
constexpr inline S div_rounding_up(const S& dividend, const T& divisor)
{
return (dividend + divisor - 1) / divisor;
}
This has (at least) the following deficiences, or what may be seen as deficiencies:
- While it works "as promised" with negative operands - it's called
div_rounding_up
- it would probably make more sense to have this kind of function round away-from-zero, sincex / y
for negativex
and positivey
rounds towards zero. In other words, maybe what I should be implementing isdiv_rounding_away_from_zero
, which would be commutative with inversion: Lettingauto f = [&y](const S& x) { return div_rounding_away_from_zero(x,y); }
we would havef(-x) == -f(x)
. - Overflow near the end of the domain of
S
. - Possibly weird behavior when
sizeof(S) > sizeof(T)
. - long function name...
While you can easily think of ways of addressing each of these, they then result in other possible deficiencies, like conditionals in the code, or a reliance on calculating the modulus which may be expensive.
So is there a "right way" to implement this? By "right" I mean semantically pleasing, efficient, avoiding as many of the deficiencies above, and hopefully widely-used.
Notes:
- If you think the function should be strictly constained to only work with non-negative arguments, say so. That would be a bit problematic IMHO since we don't want to constrain the types to be unsigned, and we don't want to check the operands' signs. That seems like something I would use a contact for - and C++ doesn't have them yet.
- Is using
std::div
and variants a good idea here? - Performance is more important than readability. At worst one can add a comment.
- Code should not be single-architecture-specific (but if you want to ifdef-else for different architectures then be my guest).
- Code should not assume a specific compiler.