Answered by:
System.Math.Round unexpected behaviour? Bug?

The following are some results for calling System.Math.Round:
System.Math.Round(2.255d, 2)
2.26System.Math.Round(0.255d, 2)
0.26System.Math.Round(3.255d, 2)
3.26System.Math.Round(4.255d, 2)
4.26System.Math.Round(5.255d, 2)
5.26System.Math.Round(1.255d, 2)
1.25Shouldn't that last value be 1.26 in line with the previous results and the banker's rounding method used by default in the Math.Round method? Any ideas anyone?
This behaviour was found in both, the 1.1 and 2.0 frameworks.
Question
Answers

Welcome to computer floatingpoint math... See What Every Computer Scientist Should Know About FloatingPoint Arithmetic.
What you're encountering is rounding error. What is happening is 1.255d is multiplied by 100d before Math.Round() is called to round to the next integer. 1.255d multiplied by 100d results in 125.4999999... which, of course rounds down to 125.0d.

So, thinking about it and reading the article you sent, 1.255d is as special as 1/3.
Just as 1/3 cannot be represent exactly as base 10 fractional number (0.333333...), 1.255d or 1.1d or 1.277d cannot be represented exactly as base 2 fractional numbers when translated into the internal representation of the floating point number.
This article also helped me understand it better:
http://www.yoda.arachsys.com/csharp/floatingpoint.html
All replies

Welcome to computer floatingpoint math... See What Every Computer Scientist Should Know About FloatingPoint Arithmetic.
What you're encountering is rounding error. What is happening is 1.255d is multiplied by 100d before Math.Round() is called to round to the next integer. 1.255d multiplied by 100d results in 125.4999999... which, of course rounds down to 125.0d.

Thanks for the reply Ritchie. I had also seen that that was the algorithm to round using reflector  make the number whole, round using a method inside the CLR, then give the number its fractional part again.
I'm familiar with floating point math, and many of the potential pitfalls (comparing numbers, order of operations, etc); however, I'm still puzzled as to why:
0.255d * 10d
2.551.355d * 100d
135.52.255d * 100d
225.53.255d * 100d
325.51.255d * 100d
125.49999999999999Shouldn't all these values have the same number of significant digits in the mantissa prior to the multiplication? What's so special about 1.255d?

So, thinking about it and reading the article you sent, 1.255d is as special as 1/3.
Just as 1/3 cannot be represent exactly as base 10 fractional number (0.333333...), 1.255d or 1.1d or 1.277d cannot be represented exactly as base 2 fractional numbers when translated into the internal representation of the floating point number.
This article also helped me understand it better:
http://www.yoda.arachsys.com/csharp/floatingpoint.html


The default for Math.Round is banker's rounding. In .NET 2.0 they added the ability to choose what type of rounding you require. If you want different rounding then you can use a member of the MidpointRounding enum. In the case of 5.65 to 5.7 you'd have to use MidpointRounding.ToEven, but that would give you a different type of result for 4.65.
If you always want to round up you can use Math.Ceiling after multiplying the number by the factor you want rounded to then dividing the result by the same factor. For example, if you want to round up 5.65 to the first decimal place: Math.Ceiling(5.65 * 10.0)/10.0.