Click here to Skip to main content
Click here to Skip to main content

Round to a multiple (Quantization)

, 26 Mar 2011
Rate this:
Please Sign up or sign in to vote.
This article provides some code snippets for rounding to a multiple for doubles, decimals and integers.

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; // get remainder
    if (prem < 0)
        prem += multiple;    // turn into positive remainder
    i -= prem;               // round i toward minus infinity
    if (prem * 2 > multiple) // round upward 
        return i + multiple;
    if (prem * 2 < multiple) // round downward
        return i;
    //bitch case - round to even
    if ((i / multiple) % 2 == 0) // is current rounding even?
        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 Wink | ;-)
 
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[^]

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

jiquera

Netherlands Netherlands
No Biography provided

Comments and Discussions

 
GeneralRound half to even is also known as bankers rounding. http:/... PinmentorDaveAuld23-Mar-11 7:26 
GeneralReason for my vote of 5 Excellent and useful little article.... PinmemberMacMaverick23-Mar-11 6:53 
GeneralRe: Well thanks! Thanks for the 'improvement' as well ;-) Pinmemberjiquera25-Mar-11 3:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 26 Mar 2011
Article Copyright 2011 by jiquera
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid