How can I ensure that a division of integers is always rounded up?

C#Math

C# Problem Overview


I want to ensure that a division of integers is always rounded up if necessary. Is there a better way than this? There is a lot of casting going on. :-)

(int)Math.Ceiling((double)myInt1 / myInt2)

C# Solutions


Solution 1 - C#

UPDATE: This question was the subject of my blog in January 2013. Thanks for the great question!


Getting integer arithmetic correct is hard. As has been demonstrated amply thus far, the moment you try to do a "clever" trick, odds are good that you've made a mistake. And when a flaw is found, changing the code to fix the flaw without considering whether the fix breaks something else is not a good problem-solving technique. So far we've had I think five different incorrect integer arithmetic solutions to this completely not-particularly-difficult problem posted.

The right way to approach integer arithmetic problems -- that is, the way that increases the likelihood of getting the answer right the first time - is to approach the problem carefully, solve it one step at a time, and use good engineering principles in doing so.

Start by reading the specification for what you're trying to replace. The specification for integer division clearly states:

  1. The division rounds the result towards zero

  2. The result is zero or positive when the two operands have the same sign and zero or negative when the two operands have opposite signs

  3. If the left operand is the smallest representable int and the right operand is –1, an overflow occurs. [...] it is implementation-defined as to whether [an ArithmeticException] is thrown or the overflow goes unreported with the resulting value being that of the left operand.

  4. If the value of the right operand is zero, a System.DivideByZeroException is thrown.

What we want is an integer division function which computes the quotient but rounds the result always upwards, not always towards zero.

So write a specification for that function. Our function int DivRoundUp(int dividend, int divisor) must have behaviour defined for every possible input. That undefined behaviour is deeply worrying, so let's eliminate it. We'll say that our operation has this specification:

  1. operation throws if divisor is zero

  2. operation throws if dividend is int.minval and divisor is -1

  3. if there is no remainder -- division is 'even' -- then the return value is the integral quotient

  4. Otherwise it returns the smallest integer that is greater than the quotient, that is, it always rounds up.

Now we have a specification, so we know we can come up with a testable design. Suppose we add an additional design criterion that the problem be solved solely with integer arithmetic, rather than computing the quotient as a double, since the "double" solution has been explicitly rejected in the problem statement.

So what must we compute? Clearly, to meet our spec while remaining solely in integer arithmetic, we need to know three facts. First, what was the integer quotient? Second, was the division free of remainder? And third, if not, was the integer quotient computed by rounding up or down?

Now that we have a specification and a design, we can start writing code.

public static int DivRoundUp(int dividend, int divisor)
{
  if (divisor == 0 ) throw ...
  if (divisor == -1 && dividend == Int32.MinValue) throw ...
  int roundedTowardsZeroQuotient = dividend / divisor;
  bool dividedEvenly = (dividend % divisor) == 0;
  if (dividedEvenly) 
    return roundedTowardsZeroQuotient;

  // At this point we know that divisor was not zero 
  // (because we would have thrown) and we know that 
  // dividend was not zero (because there would have been no remainder)
  // Therefore both are non-zero.  Either they are of the same sign, 
  // or opposite signs. If they're of opposite sign then we rounded 
  // UP towards zero so we're done. If they're of the same sign then 
  // we rounded DOWN towards zero, so we need to add one.

  bool wasRoundedDown = ((divisor > 0) == (dividend > 0));
  if (wasRoundedDown) 
    return roundedTowardsZeroQuotient + 1;
  else
    return roundedTowardsZeroQuotient;
}

Is this clever? No. Beautiful? No. Short? No. Correct according to the specification? I believe so, but I have not fully tested it. It looks pretty good though.

We're professionals here; use good engineering practices. Research your tools, specify the desired behaviour, consider error cases first, and write the code to emphasize its obvious correctness. And when you find a bug, consider whether your algorithm is deeply flawed to begin with before you just randomly start swapping the directions of comparisons around and break stuff that already works.

Solution 2 - C#

All the answers here so far seem rather over-complicated.

In C# and Java, for positive dividend and divisor, you simply need to do:

( dividend + divisor - 1 ) / divisor 

Source: Number Conversion, Roland Backhouse, 2001

Solution 3 - C#

The final int-based answer

For signed integers:

int div = a / b;
if (((a ^ b) >= 0) && (a % b != 0))
    div++;

For unsigned integers:

int div = a / b;
if (a % b != 0)
    div++;

The reasoning for this answer

Integer division '/' is defined to round towards zero (7.7.2 of the spec), but we want to round up. This means that negative answers are already rounded correctly, but positive answers need to be adjusted.

Non-zero positive answers are easy to detect, but answer zero is a little trickier, since that can be either the rounding up of a negative value or the rounding down of a positive one.

The safest bet is to detect when the answer should be positive by checking that the signs of both integers are identical. Integer xor operator '^' on the two values will result in a 0 sign-bit when this is the case, meaning a non-negative result, so the check (a ^ b) >= 0 determines that the result should have been positive before rounding. Also note that for unsigned integers, every answer is obviously positive, so this check can be omitted.

The only check remaining is then whether any rounding has occurred, for which a % b != 0 will do the job.

Lessons learned

Arithmetic (integer or otherwise) isn't nearly as simple as it seems. Thinking carefully required at all times.

Also, although my final answer is perhaps not as 'simple' or 'obvious' or perhaps even 'fast' as the floating point answers, it has one very strong redeeming quality for me; I have now reasoned through the answer, so I am actually certain it is correct (until someone smarter tells me otherwise -furtive glance in Eric's direction-).

To get the same feeling of certainty about the floating point answer, I'd have to do more (and possibly more complicated) thinking about whether there is any conditions under which the floating-point precision might get in the way, and whether Math.Ceiling perhaps does something undesirable on 'just the right' inputs.

The path travelled

Replace (note I replaced the second myInt1 with myInt2, assuming that was what you meant):

(int)Math.Ceiling((double)myInt1 / myInt2)

with:

(myInt1 - 1 + myInt2) / myInt2

The only caveat being that if myInt1 - 1 + myInt2 overflows the integer type you are using, you might not get what you expect.

Reason this is wrong: -1000000 and 3999 should give -250, this gives -249

EDIT:
Considering this has the same error as the other integer solution for negative myInt1 values, it might be easier to do something like:

int rem;
int div = Math.DivRem(myInt1, myInt2, out rem);
if (rem > 0)
  div++;

That should give the correct result in div using only integer operations.

Reason this is wrong: -1 and -5 should give 1, this gives 0

EDIT (once more, with feeling):
The division operator rounds towards zero; for negative results this is exactly right, so only non-negative results need adjustment. Also considering that DivRem just does a / and a % anyway, let's skip the call (and start with the easy comparison to avoid modulo calculation when it is not needed):

int div = myInt1 / myInt2;
if ((div >= 0) && (myInt1 % myInt2 != 0))
    div++;

Reason this is wrong: -1 and 5 should give 0, this gives 1

(In my own defence of the last attempt I should never have attempted a reasoned answer while my mind was telling me I was 2 hours late for sleep)

Solution 4 - C#

Perfect chance to use an extension method:

public static class Int32Methods
{
	public static int DivideByAndRoundUp(this int number, int divideBy)
	{                        
		return (int)Math.Ceiling((float)number / (float)divideBy);
	}
}

This makes your code uber readable too:

int result = myInt.DivideByAndRoundUp(4);

Solution 5 - C#

You could write a helper.

static int DivideRoundUp(int p1, int p2) {
  return (int)Math.Ceiling((double)p1 / p2);
}

Solution 6 - C#

You could use something like the following.

a / b + ((Math.Sign(a) * Math.Sign(b) > 0) && (a % b != 0)) ? 1 : 0)

Solution 7 - C#

For signed or unsigned integers.

q = x / y + !(((x < 0) != (y < 0)) || !(x % y));

For signed dividends and unsigned divisors.

q = x / y + !((x < 0) || !(x % y));

For unsigned dividends and signed divisors.

q = x / y + !((y < 0) || !(x % y));

For unsigned integers.

q = x / y + !!(x % y);

Zero divisor fails (as with a native operation).

Cannot overflow.

Elegant and correct.

The key to understanding the behavior is to recognize the difference in truncated, floored and ceilinged division. C#/C++ is natively truncated. When the quotient is negative (i.e. the operators signs are different) then truncation is a ceiling (less negative). Otherwise truncation is a floor (less positive).

So, if there is a remainder, add 1 if the result is positive. Modulo is the same, but you instead add the divisor. Flooring is the same, but you subtract under the reversed conditions.

Solution 8 - C#

By round up, I take it you mean away form zero always. Without any castings, use the Math.DivRem() function

/// <summary>
/// Divide a/b but always round up
/// </summary>
/// <param name="a">The numerator.</param>
/// <param name="b">The denominator.</param>
int DivRndUp(int a, int b)
{
    // remove sign
    int s = Math.Sign(a) * Math.Sign(b);
    a = Math.Abs(a);
    b = Math.Abs(b);
    var c = Math.DivRem(a, b, out int r);
    // if remainder >0 round up
    if (r > 0)
    {
        c++;
    }
    return s * c;
}

If roundup means always up regardless of sign, then

/// <summary>
/// Divide a/b but always round up
/// </summary>
/// <param name="a">The numerator.</param>
/// <param name="b">The denominator.</param>
int DivRndUp(int a, int b)
{
    // remove sign
    int s = Math.Sign(a) * Math.Sign(b);
    a = Math.Abs(a);
    b = Math.Abs(b);
    var c = Math.DivRem(a, b, out int r);
    // if remainder >0 round up
    if (r > 0)
    {
        c+=s;
    }
    return s * c;
}

Solution 9 - C#

Some of the above answers use floats, this is inefficient and really not necessary. For unsigned ints this is an efficient answer for int1/int2:

(int1 == 0) ? 0 : (int1 - 1) / int2 + 1;

For signed ints this will not be correct

Solution 10 - C#

The problem with all the solutions here is either that they need a cast or they have a numerical problem. Casting to float or double is always an option, but we can do better.

When you use the code of the answer from @jerryjvl

int div = myInt1 / myInt2;
if ((div >= 0) && (myInt1 % myInt2 != 0))
    div++;

there is a rounding error. 1 / 5 would round up, because 1 % 5 != 0. But this is wrong, because rounding will only occur if you replace the 1 with a 3, so the result is 0.6. We need to find a way to round up when the calculation give us a value greater than or equal to 0.5. The result of the modulo operator in the upper example has a range from 0 to myInt2-1. The rounding will only occur if the remainder is greater than 50% of the divisor. So the adjusted code looks like this:

int div = myInt1 / myInt2;
if (myInt1 % myInt2 >= myInt2 / 2)
    div++;

Of course we have a rounding problem at myInt2 / 2 too, but this result will give you a better rounding solution than the other ones on this site.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKarstenView Question on Stackoverflow
Solution 1 - C#Eric LippertView Answer on Stackoverflow
Solution 2 - C#Ian NelsonView Answer on Stackoverflow
Solution 3 - C#jerryjvlView Answer on Stackoverflow
Solution 4 - C#joshcomleyView Answer on Stackoverflow
Solution 5 - C#JaredParView Answer on Stackoverflow
Solution 6 - C#Daniel BrücknerView Answer on Stackoverflow
Solution 7 - C#evoskuilView Answer on Stackoverflow
Solution 8 - C#John AlexiouView Answer on Stackoverflow
Solution 9 - C#Tom MensinkView Answer on Stackoverflow
Solution 10 - C#raboniView Answer on Stackoverflow