CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Feb 2012
    Posts
    4

    Basic Question about Math.Round and {0:C}

    I'm just running through a C# book and had a question, In my visual studio 2010 I put this code in:

    double inflation = .04, initialCost = 1.00, finalCost = 0, cost = 0, years = 3;
    cost = initialCost * inflation + initialCost;
    cost = cost * inflation + cost;
    finalCost = cost * inflation + cost;
    finalCost = Math.Round(finalCost, 3);

    Console.WriteLine("In {0} years the item will cost {1:C} with a starting cost of {2:C} and an inflation rate of {3} ", years,finalCost, initialCost, inflation);

    My question: With the" finalCost = Math.Round(finalCost, 3);" my output for finalCost is 1.13 but if I comment it out I get 1.12 output for finalCost.

    Can someone tell me why this is and if I'm missing something?

  2. #2
    Join Date
    Feb 2012
    Posts
    4

    Re: Basic Question about Math.Round and {0:C}

    Here is it properly formatted with the tags

    I'm just running through a C# book and had a question, In my visual studio 2010 .NET 4 I run this code in:


    Code:
    double inflation = .04, initialCost = 1.00, finalCost = 0, cost = 0, years = 3;
    cost = initialCost * inflation + initialCost;
    cost = cost * inflation + cost;
    finalCost = cost * inflation + cost;
    finalCost = Math.Round(finalCost, 3);
    
    Console.WriteLine("In {0} years the item will cost {1:C} with a starting cost of {2:C} and an inflation rate of {3} ", years,finalCost, initialCost, inflation);
    My question: With the" finalCost = Math.Round(finalCost, 3);" my output for finalCost is 1.13 but if I comment it out I get 1.12 output for finalCost.

    Can someone tell me why this is and if I'm missing something?

  3. #3
    Join Date
    Jun 2001
    Location
    Melbourne/Aus (C# .Net 4.0)
    Posts
    686

    Re: Basic Question about Math.Round and {0:C}

    The actual value of finalCost is 1.125.

    The rules of Mathematics (and therefore the Round() function) say that, when rounding to N decimal places, if the N+1th decimal digit is >4, then the Nth decimal digitis incremented.

    So in your case:

    1.125 rounded to 2 decimal places (currency) is 1.13. This is because 5 is greater than 4 and hence the 2 is incremented to 3.

    Explained much better here.
    Rob
    -
    Ohhhhh.... Old McDonald was dyslexic, E O I O EEEEEEEEEE.......

  4. #4
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Basic Question about Math.Round and {0:C}

    Actually, they are both doing the rounding, but there are differences in the approach.

    The Math.Round(double, int, MidpointRounding) variant of the method provides you with a way to explicitly set the approach to use for the midpoint case.

    There are two possibilities:
    • MidpointRounding.ToEven - If the digit in the decimals position is odd, it is changed to an even digit. Otherwise, it is left unchanged. This behavior follows IEEE Standard 754, section 4. It is sometimes called rounding to nearest, or banker's rounding. It minimizes rounding errors that result from consistently rounding a midpoint value in a single direction.
    • MidpointRounding.AwayFromZero - The digit in the decimals position is always rounded up to the next digit. This is the most commonly known rounding method. It is known as symmetric arithmetic rounding.
    The default approach for the Math.Round() method is MidpointRounding.ToEven - generally, the more precise one.

    But, if you go to the MSDN entry on the currency format specifier, you'll find this:
    If the value to be formatted has more than the specified or default number of decimal places, the fractional value is rounded in the result string. If the value to the right of the number of specified decimal places is 5 or greater, the last digit in the result string is rounded away from zero. [emphasis by me]
    Last edited by TheGreatCthulhu; February 8th, 2012 at 08:38 PM.

  5. #5
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Basic Question about Math.Round and {0:C}

    Wait... Didn't check the numbers; what you're experiencing is the opposite of what should happen. (BTW, it appears that the C format specifier rounds to 2 decimal places by default on your system, and you're telling math to round to 3).

    --- a few moments after ---
    OK, if I reproduced your program correctly, you should get the value of 1.124864
    Math.Round(finalCost, 3) should produce 1.125.

    In the away from zero mode,
    1.124864 is rounded to 1.12, and
    1.125 is rounded to 1.13.

  6. #6
    Join Date
    Feb 2012
    Posts
    4

    Re: Basic Question about Math.Round and {0:C}

    I see so generally I should just use the {0:C} and be done with it as the "Math.Round(finalCost, 3)" just complicates things. I guess it depends on which way you want to go, I just added the Math.Round(finalCost, 3) as I though it should round to 1.13 when I saw the original 1.124864 and wondered which way was the correct way. To me using the "Math.Round(finalCost, 3)" seems more correct than the {0:C}, although the {0:C} is made for currency so I guess it is correct.

    Just a question, which way would you use in a Production Environment?

    Thank you guys for your help,

    jdearing

  7. #7
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Basic Question about Math.Round and {0:C}

    Quote Originally Posted by jdearing View Post
    [...] I just added the Math.Round(finalCost, 3) as I though it should round to 1.13 when I saw the original 1.124864 [...]
    If you check the docs for Math.Round(double, int), you'll see this description for the second parameter:
    The number of fractional digits in the return value.
    So, it refers to the number of decimal places after the decimal point. That's why your program rounded to 1.125.


    Quote Originally Posted by jdearing View Post
    Just a question, which way would you use in a Production Environment?
    Depends. Generally, if you wanted to round numbers for various calculations, like in a physics-based simulation, you would use Math.Round().

    However, note that Math.Round() and {0:C} have different purposes.
    Math.Round() changes the actual numerical data value, while {0:C} only changes the string representation of the value, without ever changing the original data.

    By using a Math.Round(double, int, MidpointRounding) overload, and setting the last parameter to AwayFromZero will get you the same behavior as with {0:C}, in terms of how the rounding is done, but the difference in whether the original data is affected or not still remains.

    So, it's like this: if you just want to round the number for display, so that a user (human) can read it with more ease, use {0:C}, and leave the original number unchanged, maintaining the more accurate, higher precision value internally. The user usually only cares for the value to be precise up to a number of decimal places.
    If, OTOH, you need to work with rounded values in your internal calculation, then use Math.Round(). For example, you might want to do this if you're performing calculations with doubles, so that you can have greater precision, but ultimately only need an integer value. Use Math.Round() if you need rounding in your implementation regardless of whether you're gonna display the result as text or not.

  8. #8
    Join Date
    Feb 2012
    Posts
    4

    Re: Basic Question about Math.Round and {0:C}

    I see, Thank you.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured