Peterson's Ponderings

Technical findings, ideas, thoughts and news directly from me.
in

An Option for Rounding

The Math.Round function in Visual Studio 2005 got a slight make over.  If you recall, in VS 2003 Math.Round always implemented the 'bankers rounding' which was if the number was at the half way point between an even an odd number it would always round to the even number.  i.e. 2.5 rounded to 2 and 3.5 rounded to 4.  This was obviously a bit confusing and unexpected to a lot of programmers with math backgrounds and not banker backgrounds, as in math you expect it to always round up if the decimal was at the half-way point. 

In VS 2005 you can now specify with a parameter whether you want to round with the bankers method or the mathematical.  The Round method now has an overload allowing a MidpointRounding enumeration for you to specify.  The options for the enumeration are ToEven and AwayFromZero.  Away from zero will always force rounding of a number at the half way point to round to the next higher number away from zero (i.e. -3.5 goes to -4 and 3.5 goes to 4).  If you don't use the overload then the method continues to work in the bankers rounding mode so make sure if you are porting code from 2003 to 2005 to change your Round method to utilize the overload in the proper scenarios.

 

Comments

OSmar Fernandez said:

Not True.
Try Math.Round(.285,2,AwayfromZero)
The Result Should be .29, but you get .28
This is still a problem.
# August 17, 2006 8:27 AM

dpeterson said:

Interesting Osmar, this seems to be an odd scenario I can't explain.  I tried every other tenth digit for .2x5 and they all rounded correctly except for .285.  I'm not sure why this would be, but for every other number I've tried it for it has worked correctly.  Here are my results from the immediate window testing the tenth places.  Only the .285 didn't work, if AwayfromZero wasn't working at all the other even numbers wouldn't have rounded either.

? Math.Round(.205,2,MidpointRounding.AwayFromZero)
0.21
? Math.Round(.215,2,MidpointRounding.AwayFromZero)
0.22
? Math.Round(.225,2,MidpointRounding.AwayFromZero)
0.23
? Math.Round(.235,2,MidpointRounding.AwayFromZero)
0.24
? Math.Round(.245,2,MidpointRounding.AwayFromZero)
0.25
? Math.Round(.255,2,MidpointRounding.AwayFromZero)
0.26
? Math.Round(.265,2,MidpointRounding.AwayFromZero)
0.27
? Math.Round(.275,2,MidpointRounding.AwayFromZero)
0.28
? Math.Round(.285,2,MidpointRounding.AwayFromZero)
0.28
? Math.Round(.295,2,MidpointRounding.AwayFromZero)
0.3
? Math.Round(0.285,2,MidpointRounding.AwayFromZero)
0.28
? Math.Round(1.285,2,MidpointRounding.AwayFromZero)
1.29
? Math.Round(2.285,2,MidpointRounding.AwayFromZero)
2.29
? Math.Round(3.285,2,MidpointRounding.AwayFromZero)
3.29
# August 17, 2006 8:20 PM

Jerry Huang said:

I guess this is the floating rounding error, you may avoid this rounding error by

---------------------------------------------------------------------------

? Math.Round(0.285d, 2, MidpointRounding.AwayFromZero)  

0.29D

? Math.Round(0.285, 2, MidpointRounding.AwayFromZero)  

0.28

---------------------------------------------------------------------------

0.285d means convert 0.285(double) to 0.285(decimal)

# November 26, 2008 9:36 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)