C#: How do I do simple math, with rounding, on integers?
Solution 1
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));
Solution 2
int height2 = (width2 * height1) / width1;
Solution 3
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.
Solution 4
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?
Solution 5
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.
Related videos on Youtube
mistertodd
Any code is public domain. No attribution required. జ్ఞా <sup>🕗</sup>🕗 Yes, i do write i with a lowercase i. The Meta Stackexchange answer that I am most proud of
Updated on July 07, 2020Comments
-
mistertodd almost 4 years
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) );
-
mistertodd over 14 yearsIt's sad that after a year i still have to come back to reference this question in order to figure how to do math in C#. In delphi i would just type "137 * 3/4" and it would work. But not C#, C# forces you to pray to the compiler gods before you can do what you want.
-
-
mistertodd over 15 yearsThe 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)
-
mistertodd over 15 yearsSince 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?
-
mistertodd over 15 yearsi.e. is 79.99999999 worse than 79.99999999999
-
rwallace over 15 yearsYes. 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!
-
Steven over 14 yearsdoesn't help. still gets 102
-
mistertodd over 14 yearsWith the benefit of a year of hindsight: can you explain why i should do multiplication first?
-
mistertodd over 14 yearsCan 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?
-
plinth over 14 yearsMultiplication 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).
-
Catch22 over 12 yearsThis solution only rounds down and will not round up if required. For example if width1 = (width2*height1 + 1), then (width2 * height1)/width1 results in 0, not 1. In other words if the divisor is slightly larger than the dividend, then integer division will produce 0 while floating point division with rounding will produce 1.
-
Jeffrey L Whitledge over 12 years@Catch22 - Yes, that is an excellent point. The version with float conversions is a better answer.
-
craastad almost 11 yearsMath.round(...) returns a double and not an int (so there will be more casting involved) msdn.microsoft.com/en-us/library/75ks3aby.aspx
-
supercat over 10 years@IanBoyd: What's 16777216.0f + 1.0f?
-
supercat over 10 years@IanBoyd: Have you tried it? Unless you're using a language which promotes
float
todouble
, 16777216.0f+1.0f yields 16777216.0f, since there are nofloat
values between 16777216.0f and 16777218.0f. -
RenniePet almost 10 yearsThere's something wrong with your first example, you're missing the division by 7. And your very first sentence says something different from what you're doing in all of your examples, as far as I can understand it.
-
RenniePet almost 10 yearsShould be "int height2 = ((width2 * height1 * 10) + width1 * 5) / (width1 * 10);"
-
supercat almost 10 years@RenniePet: Is that better?