Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rounding integer division (instead of truncating)

I was curious to know how I can round a number to the nearest whole number. For instance, if I had:

int a = 59 / 4; 

which would be 14.75 if calculated in floating point; how can I store the result as 15 in "a"?

like image 372
Dave Avatar asked Mar 11 '10 05:03

Dave


People also ask

Does integer division round or truncate?

As written, you're performing integer arithmetic, which automatically just truncates any decimal results.

How do you round up the result of integer division?

You'll want to do floating point division, and then use the ceiling function, to round up the value to the next integer.

What is truncating integer division?

Truncating division is division where a fractional result is converted to an integer by rounding towards zero. If both operands are ints, then other must not be zero.


2 Answers

The standard idiom for integer rounding up is:

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

You add the divisor minus one to the dividend.

like image 123
Jonathan Leffler Avatar answered Oct 16 '22 03:10

Jonathan Leffler


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; } 
like image 35
ericbn Avatar answered Oct 16 '22 02:10

ericbn