Thursday, June 15, 2006

Rounding in .NET

I was having an issue on at work, where I needed to determine how tall to make a Farpoint Spread row to display some text. I would calculate the size of some text to be entered into a table cell. Then I would take the length of the text, based on the font and divide it by the width of the cell and voila, I should have the number of lines that need to be displayed. However, I was having a problem with some of my tests. About half of the time, I ended up missing a line.

As I looked closer I noticed that all of the variables in my calculation were integers. A ha! .Net was rounding stuff for me, using its default Banker's Rounding system.

If you are unfamiliar with Banker's Rounding, or aren't a banker, then this way of rounding may seem insane to you. Let me explain. In Banker's Rounding everything works just like in regular rounding, except when dealing with halves. So anything less than .5 will always round down and anything greater than .5 will always round up. But when we have exactly .5 then we round to the closest even number. You are probably used to .5 always rounding up. This is a little known, yet extremely important behavior and I hope to have saved you some heartache. Lets see some Bankers Rounding in action:

`1.49 ==> 11.50 ==> 22.50 ==> 22.51 ==> 3`

Back to my issue. I needed a way to always round up, no matter what the decimal. Enter the Math.Ceiling function. The Math.Ceiling function returns the next whole number greater than the decimal that you started with. Here it is in action:

`System.Math.Ceiling(1.0) ==> 1System.Math.Ceiling(1.3) ==> 2`

Alternatively, if you want to always round down, you could use the Math.Floor function. It returns the next lowest whole number from the starting decimal.

`System.Math.Floor(2.0) ==> 2System.Math.Floor(1.9) ==> 1`