Arithmetic Rounding in .Net
Quiz time: what is the value of test after the following code runs:
.csharpcode
{
font-size: 10pt;
color: black;
font-family: Courier New , Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0px; }
.rem { color: #008000; }
.kwrd { color: #0000ff; }
.str { color: #006080; }
.op { color: #0000c0; }
.preproc { color: #cc6633; }
.asp { background-color: #ffff00; }
.html { color: #800000; }
.attr { color: #ff0000; }
.alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0px;
}
.lnum { color: #606060; }
.csharpcode
{
font-size: 10pt;
color: black;
font-family: Courier New , Courier, Monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0px; }
.rem { color: #008000; }
.kwrd { color: #0000ff; }
.str { color: #006080; }
.op { color: #0000c0; }
.preproc { color: #cc6633; }
.asp { background-color: #ffff00; }
.html { color: #800000; }
.attr { color: #ff0000; }
.alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0px;
}
.lnum { color: #606060; }
decimal test = decimal.Round(12.345m, 2);
12.35, right? No - imagine my surprise to find that it returns 12.34!! It turns out that .Net employs a type of rounding called "banker's rounding". When the rounding logic encounters a midpoint (like the 5 in my example), rather than always rounding up, it rounds to then nearest even number. Of course, in my situation, I needed the traditional "arithmetic rounding" which always goes up (or away from zero) when a midpoint is encountered. Finding no such feature in .Net, I wrote my own. If you see any bugs in it, let me know! (Note: code updated based on input from Ramon and Edward)
public static decimal ArithmeticRound (decimal d, int decimals)
{
decimal power = (decimal)Math.Pow(10, decimals);
// Note: converting to positive number before calculating rounding, so that we don't need separate logic for negative number handling
decimal result = decimal.Floor((Math.Abs(d) * power) + 0.5m) / power;
return result * Math.Sign(d);
}
BTW, .Net 2 provides an option on the Round function to use either type of rounding. See
http://msdn2.microsoft.com/library/wxhaazw6(en-us,vs.80).aspx.