tags:

views:

5532

answers:

7

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)
   );
+5  A: 
int height2 = (width2 * height1) / width1;
Jeffrey L Whitledge
A: 

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.

James Curran
+3  A: 

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.

plinth
With the benefit of a year of hindsight: can you explain *why* i should do multiplication first?
Ian Boyd
Multiplication ends up shifting digits to the left. Division shifts to the right. If the multiplication doesn't result in overflow, no precision is lost. Division is highly likely to lose precision since you will lose bits (if you divide by 2, you lose 1 bit, if you divide by 16 you lose 4, etc).
plinth
+2  A: 

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));
Aaron
A: 

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.

dongilmore
doesn't help. still gets 102
Steven
A: 

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.

superjoe30
The orginal values are integers and can only contain integers. The question is then how to do math with them. If i was performing floating-point math i would have asked that. (actually, not really, since FP math wouldn't have the problem)
Ian Boyd
+1  A: 

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.

rwallace
Since i'll be rounding to a 32-bit integer anyway, does it matter than the double has a meaningful digit in the 8th place after the decimal and float does not?
Ian Boyd
i.e. is 79.99999999 worse than 79.99999999999
Ian Boyd
Yes. 32 bit int is about 9 digits, but 32 bit float is only about 7. And remember: code that occasionally gives a slightly wrong answer is the worst kind of bug, much worse than always getting a completely wrong answer!
rwallace
Can you come up with any example where Single math converted to a 32-bit integer gives the wrong answer, where Double math converted to a 32-bit integer is right?
Ian Boyd