Rounding numbers with .NET
Everyone can round numbers, right? At least I thought I can. "What's happen?" you may ask. Lets go for example.
What do you think you got from this:
class MyRoundings
{
static void Main()
{
Console.WriteLine( System.Math.Round(2.15,1) );
Console.WriteLine( System.Math.Round(2.25,1) );
Console.ReadLine();
}
}
If you think that you get (naturally):
2.2
2.3
then maybe it is time when you should try this yourself. Really.
Sometimes long, long ago I was taught that rounding works somewhat like this: "under five down, five and more up". And that works. Works in Excel, T-SQL, JScript.
But it seems that .NET Framework Library System.Math.Round() call work somewhat otherwise. But how?
Quick look into MSDN Library (one must do sometime even this when everything else fails) put some light on this.
First take do not help much. Description on common page for System.Math.Round() methods reads:
"Returns the number nearest the specified value."
Specific help page for given method's overload System.Math.Round(Double, Int32) helps more. It reads:
Return Value
The number nearest value with precision equal to digits. If value is halfway between two numbers, one of which is even and the other odd, then the even number is returned. If the precision of value is less than digits, then value is returned unchanged.
Remarks
...
The behavior of this method follows IEEE Standard 754, section 4. This kind of rounding is sometimes called rounding to nearest, or banker's rounding. If digits is zero, this kind of rounding is sometimes called rounding toward zero.
Well, so they use some different rounding algorithm. But why they do not use same with for all products/libraries?
Few minutes later I found this useful MS KB article (Q196652) that completely clear this up.
So, conclusion. Algorithm I know so far is called "symmetric arithmetic rounding" and in .NET FCL is used "banker's rounding". There are few others rounding algorithms, too. It seems that for example Java use "asymmetric arithmetic rounding".
Well, again I learned something new.
UPDATE:
btw, there is, in .NET Framework library, also method System.Data.SqlTypes.SqlDecimal.Round() which mimic behaviour of T-SQL ROUND function (except for such freaky calls like "ROUND(748.55, -3)"), so it use "normal" symmetric arithmetic rounding algorithm.