c – Implementing banker’s rounding for integer division
If the result is non-negative (a and b have same sign, i.e. both are non-negative or both are negative), then the normally rounded division result is
x = (a + b/2) / b;
where an exact half is rounded towards +infinity.
If the result is negative, then the normally rounded division result is:
x = (a - b/2) / b;
where an exact half is rounded towards -infinity.
This is equal to the result of “banker’s rounding” except if x is odd and the rounding was from an exact half. An exact half is obtained if “a/b=x-½” or equivalently, “b * x = a + b/2” (in the “non-negative” case) or “b * x = a – b/2” (in the “negative” case) and if that happens, then x must be decremented/incremented by 1 to get the correct result.
Notice that if b is odd, then with a and b being integers, it is not possible for “a/b” to have a fractional part of exactly ½. So the intermediate result only may need correction if b is even and in that case, the conditions above involve only integer terms.
All in all, we have:
int divround(int a, int b)
{
int x;
if((a<0) == (b<0))
{ // a and b have same sign
x = (a + b/2) / b;
if((b%2 == 0) && (x%2 != 0) && (b*x == a + b/2)) // b even, x odd and a/b=x-1/2
{
x--;
}
}
else
{ // a and b have different sign
x = (a - b/2) / b;
if((b%2 == 0) && (x%2 != 0) && (b*x == a - b/2)) // b even, x odd and a/b=x+1/2
{
x++;
}
}
return x;
}
Of course, if a and b are required to be non-negative, then only the first case in the if–else-statement is needed.
A few test cases:
divround(3, 2) == 2
divround(-3, 2) == -2
divround(3, -2) == -2
divround(-3, -2) == 2
divround(5, 2) == 2
divround(-5, 2) == -2
divround(5, -2) == -2
divround(-5, -2) == 2
divround(5, 1) == 5
divround(5, -1) == -5
divround(5, 3) == 2
divround(5, -3) == -2
divround(0, 2) == 0
divround(0, -2) == 0
Read more here: Source link
