Question

i want the result of an equation rounded to the nearest integer. e.g.

137 * (3/4) = 103

Consider the following incorrect code.

int width1 = 4;
int height1 = 3;

int width2 = 137;
int height2 = width2 * (height1 / width1);

What is the proper way to perform "integer" math in C#?

Do i really have to do:

int height2 = (int)Math.Round(
      (float)width2 * ((float)height1 / (float)width1)
   );
Was it helpful?

Solution

As said above, you should do the multiplication before the division. Anyway you could write your expression with casting only the divisor:

int height2 = (int)Math.Round(width2 * (height1 / (float)width1));

OTHER TIPS

int height2 = (width2 * height1) / width1;

Do multiplication first (as long as they're not likely to overflow) and division second.

3/4 == 0 in integer math (integer math doesn't round on division, it truncates).

If you really need rounding, you have to either work in fixed point, floating point, or play around with the modulus.

I think this is the most elegant way to do this:

Math.round(myinteger * 0.75);

Using 0.75 instead of 3/4 will implicitly cast it to an double/float and why not use the default functions that are provided for this?

I will fix the incorrect code by adding zero lines of code:

float width1 = 4;
float height1 = 3;

float width2 = 137;
float height2 = width2 * (height1 / width1);

You should use floats for variables that can possibly contain decimals. This includes heights calculated from ratios. You can always cast to int later if that is a problem.

Never cast to float, it has even less precision than a 32-bit integer. If you're going to use floating point, always use double instead of float.

Just stumbled upon this question. Aaron's answer seems almost right to me. But I'm very sure you need to specify midpointrounding if your problem is a "real world" problem. So my answer, based on Aaron's code, is

int height2 = (int)Math.Round(width2 * (height1 / (float)width1),MidpointRounding.AwayFromZero);

To see the difference run that code in console

    Console.WriteLine((int)Math.Round(0.5));
    Console.WriteLine((int)Math.Round(1.5));
    Console.WriteLine((int)Math.Round(2.5));
    Console.WriteLine((int)Math.Round(3.5));
    Console.WriteLine((int)Math.Round(0.5, MidpointRounding.AwayFromZero));
    Console.WriteLine((int)Math.Round(1.5, MidpointRounding.AwayFromZero));
    Console.WriteLine((int)Math.Round(2.5, MidpointRounding.AwayFromZero));
    Console.WriteLine((int)Math.Round(3.5, MidpointRounding.AwayFromZero));
    Console.ReadLine();

For details you may look at this article.

Six years (rounded) later, here's my contribution - a little trick I learned long ago, and am surprised that nobody else has mentioned here.

The idea is to do rounding by adding half of the divisor to the numerator before doing the division.

    int height2 = (width2 * height1 + width1 / 2) / width1;

In reality I wouldn't necessarily recommend doing that in cases, like the OP's, where the divisor is a variable. Instead it may be better to use Math.Round(), as it's much easier to understand.

But in cases where the divisor is a constant I do use this trick. So instead of

    int height2 = width2 * height1 / 4;  // No rounding

I'd use

    int height2 = (width2 * height1 + 2) / 4;

Here's a more typical example

  private static Size ResizeWithPercentage(Size oldSize, int resizePercentage)
  {
     return new Size((oldSize.Width * resizePercentage + 50) / 100, 
                     (oldSize.Height * resizePercentage + 50) / 100);
  }

Another possibility is to combine this trick with the idea mentioned by dongilmore and supercat that instead of having a division by two specified or implied, you can multiply both the numerator and denominator by two.

    int height2 = (width2 * height1 * 2 + width1) / (width1 * 2);

This gives better answers in cases where the divisor is, or may be, an odd number.

The elaborate on Jeffery's message, since you generally a better chance of truncated needed decimals than you have of overflowing a 32-bit integer (and because multiplication & division is commutative), you should generally do multiplication before division.

Convert's conversions always round so:

int height2 = Convert.ToInt32(width2 * height1 / (double)width1);
int height2 = ((width2 * height1 * 10) + 5) / (width1 * 10);

Prior to any integer division, check to make certain the divisor is not zero. Also note this assumes positive quotient. If negative, roundoff needs to be -5, not +5.

A reasonably effective approach if the final division will be by an even number and the result will always be positive is to divide by half that value, add one, and divide by two. If the result may be negative, you should if possible add an amount that will make everything be positive, do the computation, and then subtract a corresponding amount afterward.

If the final division will be by an odd number, multiply both numerator and denominator by 2, then proceed as above. For example, to compute a*5/7, rounded, compute (a*10+1)>>1. The one thing to watch out for is that you may need to extend your values to a larger numeric type to avoid overflow or, if that isn't possible, subdivide the division into pieces. For example, to compute a*14/15, you might compute ((a*4/3*7)/5+1)/2. That computation may still overflow if a is too big, but the allowable range will be three times as big as if it was evaluated without doing the divide by 3 before the other division. Note that subdividing the operation will make the rounding slightly less precise, but still close enough for many purposes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top