C#: How do I do simple math, with rounding, on integers?

49,301

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.

Share:
49,301

Related videos on Youtube

mistertodd
Author by

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, 2020

Comments

  • mistertodd
    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
      mistertodd over 14 years
      It'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
    mistertodd over 15 years
    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)
  • mistertodd
    mistertodd over 15 years
    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?
  • mistertodd
    mistertodd over 15 years
    i.e. is 79.99999999 worse than 79.99999999999
  • rwallace
    rwallace over 15 years
    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!
  • Steven
    Steven over 14 years
    doesn't help. still gets 102
  • mistertodd
    mistertodd over 14 years
    With the benefit of a year of hindsight: can you explain why i should do multiplication first?
  • mistertodd
    mistertodd over 14 years
    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?
  • plinth
    plinth over 14 years
    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).
  • Catch22
    Catch22 over 12 years
    This 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
    Jeffrey L Whitledge over 12 years
    @Catch22 - Yes, that is an excellent point. The version with float conversions is a better answer.
  • craastad
    craastad almost 11 years
    Math.round(...) returns a double and not an int (so there will be more casting involved) msdn.microsoft.com/en-us/library/75ks3aby.aspx
  • supercat
    supercat over 10 years
    @IanBoyd: What's 16777216.0f + 1.0f?
  • supercat
    supercat over 10 years
    @IanBoyd: Have you tried it? Unless you're using a language which promotes float to double, 16777216.0f+1.0f yields 16777216.0f, since there are no float values between 16777216.0f and 16777218.0f.
  • RenniePet
    RenniePet almost 10 years
    There'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
    RenniePet almost 10 years
    Should be "int height2 = ((width2 * height1 * 10) + width1 * 5) / (width1 * 10);"
  • supercat
    supercat almost 10 years
    @RenniePet: Is that better?