Introduction
The default
Math
functions let you round to a certain number of digits. But sometimes that won't do, this article provides some functions for rounding to a multiple. The functions for doubles and integers are straight forward, but for educational purposes and if you don't want to use doubles or Math functions, I also provided a function for integers.
Background
Let's talk a bit about rounding here. What is rounding? Wiki states: "Rounding a numerical value means replacing it by another value that is approximately equal but has a shorter, simpler, or more explicit representation.
So we want a simpler representation of our value but one which is as close as possible to the original value. For most cases, it is clear what should be done. However if want to round 0.5 to an integer value, we have to choose between 0 and 1. We have multiple options to deal with halves listed below. We will be using the following example set {-1.5, -2.5, 0.5, 3.5, 1.5, 2.5, 1.3, 1.7} with an average of 0.875.
Round half up
Halves are always rounded up (toward infinity). So rounding our sample set to integers would result in {-1, -2, 1, 4, 2, 3, 1, 2} with an average of 1.25. Our average changed quite a lot (over 40% off) this is because this way of rounding is positively biased.
Round half away from zero
Halves are always rounded away from zero (round(-0.5)==-1 and round(0.5)==1). Let's round our sample set again: {-2, -3, 1, 4, 2, 3, 1, 2} with an average of 1. Well it's closer to our original average but it's still a bit off. This method has a positive bias for positive values and a negative bias for negative values. Because ours has more positive values than negative, the overall result has a positive bias.
Round half to even
Halves are rounded to the closest even value (in our case even multiple). This means that sometimes it will round down and sometimes it will round up. Rounding our set: {-2, -2, 0, 4, 2, 2, 1, 2} with an average of 0.875. Of course, depending on our sample set, there will still be a bias since this method introduces a positive bias for even values and a negative for odd values. However in practice this works out quite well. This method is widely used in bookkeeping and is the standard many programming languages. This is the method we will be using to round our values to multiples.
Using the code
The
Math
library in C# provides a
Round()
function that rounds doubles and decimals to their nearest integer value (using the half-to-even method). We can use this to construct a short and simple
roundToMultiple()
function:
for doubles:
static double roundToMultiple(double d, double multiple)
{
return Math.Round(d / multiple) * multiple;
}
and the same way for decimals:
static decimal roundToMultiple(decimal d, decimal multiple)
{
return Math.Round(d / multiple) * multiple;
}
But if we don't want to use doubles, no
Math
library or just because we are stubborn we have to write the code ourselves:
static int roundToMultiple(int i, int multiple)
{
if (multiple < 0)
multiple *= -1;
int prem = i % multiple;
if (prem < 0)
prem += multiple;
i -= prem;
if (prem * 2 > multiple)
return i + multiple;
if (prem * 2 < multiple)
return i;
if ((i / multiple) % 2 == 0)
return i;
return i + multiple;
}
For all optimization fanatics (like me) this is not the most compact or efficient version but it is the best readable in my opinion and that's what matters here ;-)
cheers!
History
25 March 2011 - Added my main reference; Replaced the integer version by a more readable and compact one
16 March 2011 - Initial version
References
Wiki Rounding -
http://en.wikipedia.org/wiki/Rounding[
^]
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.