I've noticed the following inconsistency in C#/.NET. I was wondering why it is so.
Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.04, Math.Round(1.04, 1)); Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.05, Math.Round(1.05, 1)); Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.06, Math.Round(1.06, 1)); Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.14, Math.Round(1.14, 1)); Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.15, Math.Round(1.15, 1)); Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.16, Math.Round(1.16, 1)); Console.WriteLine(); Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.04, Math.Round(1.04, 1, MidpointRounding.AwayFromZero)); Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.05, Math.Round(1.05, 1, MidpointRounding.AwayFromZero)); Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.06, Math.Round(1.06, 1, MidpointRounding.AwayFromZero)); Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.14, Math.Round(1.14, 1, MidpointRounding.AwayFromZero)); Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.15, Math.Round(1.15, 1, MidpointRounding.AwayFromZero)); Console.WriteLine("{0,-4:#.0} | {1,-4:#.0}", 1.16, Math.Round(1.16, 1, MidpointRounding.AwayFromZero));
Output:
1.0 | 1.0 1.1 | 1.0 1.1 | 1.1 1.1 | 1.1 1.2 | 1.2 1.2 | 1.2 1.0 | 1.0 1.1 | 1.1 1.1 | 1.1 1.1 | 1.1 1.2 | 1.2 1.2 | 1.2
It appears that the default string formatting behaviour is to round using MidpointRounding.AwayFromZero rather than Math.Round()'s default of MidpointRounding.ToEven.
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.
In C#, Format() is a string method. This method is used to replace one or more format items in the specified string with the string representation of a specified object.In other words, this method is used to insert the value of the variable or an object or expression into another string.
As a historical note, the original Visual Basic implementation of Format$ also was inconsistent with round-to-even, aka, Banker's Rounding. The original Format$ code was written by Tim Paterson. You might recall that Tim was the author of a little program called QDOS (later known as MS-DOS) that was rather a good seller for a while there.
Perhaps this is yet another case of 25 years of backwards compatibility.
Seems this problem is worse than a "simple" inconsistency:
double dd = 0.034999999999999996; Math.Round(dd, 2); // 0.03 Math.Round(dd, 2, MidpointRounding.AwayFromZero); // 0.03 Math.Round(dd, 2, MidpointRounding.ToEven); // 0.03 string.Format("{0:N2}", dd); // "0.04"
This is absolutely bananas. Who knows where the heck it get "0.04" from.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With