Rounding integer division (instead of truncating) Rounding integer division (instead of truncating) c c

Rounding integer division (instead of truncating)


The standard idiom for integer rounding up is:

int a = (59 + (4 - 1)) / 4;

You add the divisor minus one to the dividend.


A code that works for any sign in dividend and divisor:

int divRoundClosest(const int n, const int d){  return ((n < 0) ^ (d < 0)) ? ((n - d/2)/d) : ((n + d/2)/d);}

In response to a comment "Why is this actually working?", we can break this apart. First, observe that n/d would be the quotient, but it is truncated towards zero, not rounded. You get a rounded result if you add half of the denominator to the numerator before dividing, but only if numerator and denominator have the same sign. If the signs differ, you must subtract half of the denominator before dividing. Putting all that together:

(n < 0) is false (zero) if n is non-negative(d < 0) is false (zero) if d is non-negative((n < 0) ^ (d < 0)) is true if n and d have opposite signs(n + d/2)/d is the rounded quotient when n and d have the same sign(n - d/2)/d is the rounded quotient when n and d have opposite signs

If you prefer a macro:

#define DIV_ROUND_CLOSEST(n, d) ((((n) < 0) ^ ((d) < 0)) ? (((n) - (d)/2)/(d)) : (((n) + (d)/2)/(d)))

The linux kernel macro DIV_ROUND_CLOSEST doesn't work for negative divisors!

EDIT:This will work without overflow:

int divRoundClosest( int A, int B ){if(A<0)    if(B<0)        return (A + (-B+1)/2) / B + 1;    else        return (A + ( B+1)/2) / B - 1;else    if(B<0)        return (A - (-B+1)/2) / B - 1;    else        return (A - ( B+1)/2) / B + 1;}


int a = 59.0f / 4.0f + 0.5f;

This only works when assigning to an int as it discards anything after the '.'

Edit:This solution will only work in the simplest of cases. A more robust solution would be:

unsigned int round_closest(unsigned int dividend, unsigned int divisor){    return (dividend + (divisor / 2)) / divisor;}