Sunday, August 19, 2012

Integer Rounding in ANSI C

1.Unsigned Integers

When two unsigned integers are divided, the result will be rounded down.
result = numerator / denominator;
To round up a result you must apply the following idiom:
result = (numerator + denominator - 1) / denominator;
Example:
#include<stdio.h>

int main(void)
{
    unsigned int numerator   = 50;
    unsigned int denominator = 25;
    unsigned int upResult;
    unsigned int downResult;
    double fResult;
    int i;

    for(i = 0; i < 25; i++)
    {
        fResult = (double)(numerator)/(double)(denominator);
        upResult = (numerator + denominator - 1)/denominator;
        downResult = numerator/denominator;
        printf("Numerator %3u||Denominator %3u||Result %3.2f||"
               "Round up %3u||Round down %3u\n",
               numerator, denominator, fResult, upResult, downResult);
        numerator++;
    }
    return 0;
}
/*Output:
Numerator  50||Denominator  25||Result 2.00||Round up   2||Round down   2
Numerator  51||Denominator  25||Result 2.04||Round up   3||Round down   2
Numerator  52||Denominator  25||Result 2.08||Round up   3||Round down   2
Numerator  53||Denominator  25||Result 2.12||Round up   3||Round down   2
Numerator  54||Denominator  25||Result 2.16||Round up   3||Round down   2
Numerator  55||Denominator  25||Result 2.20||Round up   3||Round down   2
Numerator  56||Denominator  25||Result 2.24||Round up   3||Round down   2
Numerator  57||Denominator  25||Result 2.28||Round up   3||Round down   2
Numerator  58||Denominator  25||Result 2.32||Round up   3||Round down   2
Numerator  59||Denominator  25||Result 2.36||Round up   3||Round down   2
Numerator  60||Denominator  25||Result 2.40||Round up   3||Round down   2
Numerator  61||Denominator  25||Result 2.44||Round up   3||Round down   2
Numerator  62||Denominator  25||Result 2.48||Round up   3||Round down   2
Numerator  63||Denominator  25||Result 2.52||Round up   3||Round down   2
Numerator  64||Denominator  25||Result 2.56||Round up   3||Round down   2
Numerator  65||Denominator  25||Result 2.60||Round up   3||Round down   2
Numerator  66||Denominator  25||Result 2.64||Round up   3||Round down   2
Numerator  67||Denominator  25||Result 2.68||Round up   3||Round down   2
Numerator  68||Denominator  25||Result 2.72||Round up   3||Round down   2
Numerator  69||Denominator  25||Result 2.76||Round up   3||Round down   2
Numerator  70||Denominator  25||Result 2.80||Round up   3||Round down   2
Numerator  71||Denominator  25||Result 2.84||Round up   3||Round down   2
Numerator  72||Denominator  25||Result 2.88||Round up   3||Round down   2
Numerator  73||Denominator  25||Result 2.92||Round up   3||Round down   2
Numerator  74||Denominator  25||Result 2.96||Round up   3||Round down   2
*/
To round to the nearest integer you have 2 methods:
Method 1:
iResult1 = (unsigned int) ( (double)(numerator) / (double)(denominator) + 0.5);
Method 2:
iResult2 = (numerator + denominator / 2) / denominator;
Observation: The second method is preferred to the first method because is faster and doesn't use floating-point division.  Also, this method is preferred if you work with embedded systems.

Example:
#include<stdio.h>

int main(void)
{
    unsigned int numerator   = 50;
    unsigned int denominator = 25;
    unsigned int iResult1;
    unsigned int iResult2;
    double fResult;
    int i;

    for(i = 0; i < 25; i++)
    {
        fResult = (double)(numerator)/(double)(denominator);
        iResult1 = (int) ( (double)(numerator) / (double)(denominator) + 0.5);
        iResult2 = (numerator + denominator/2) / denominator;
        printf("Numerator %3u||Denominator %3u||Result %3.2f||"
               "Nearest_1 %3u||Nearest_2 %3u\n",
               numerator, denominator, fResult, iResult1, iResult2);
        numerator++;
    }
    return 0;
}
/*Output:
Numerator  50||Denominator  25||Result 2.00||Nearest_1   2||Nearest_2   2
Numerator  51||Denominator  25||Result 2.04||Nearest_1   2||Nearest_2   2
Numerator  52||Denominator  25||Result 2.08||Nearest_1   2||Nearest_2   2
Numerator  53||Denominator  25||Result 2.12||Nearest_1   2||Nearest_2   2
Numerator  54||Denominator  25||Result 2.16||Nearest_1   2||Nearest_2   2
Numerator  55||Denominator  25||Result 2.20||Nearest_1   2||Nearest_2   2
Numerator  56||Denominator  25||Result 2.24||Nearest_1   2||Nearest_2   2
Numerator  57||Denominator  25||Result 2.28||Nearest_1   2||Nearest_2   2
Numerator  58||Denominator  25||Result 2.32||Nearest_1   2||Nearest_2   2
Numerator  59||Denominator  25||Result 2.36||Nearest_1   2||Nearest_2   2
Numerator  60||Denominator  25||Result 2.40||Nearest_1   2||Nearest_2   2
Numerator  61||Denominator  25||Result 2.44||Nearest_1   2||Nearest_2   2
Numerator  62||Denominator  25||Result 2.48||Nearest_1   2||Nearest_2   2
Numerator  63||Denominator  25||Result 2.52||Nearest_1   3||Nearest_2   3
Numerator  64||Denominator  25||Result 2.56||Nearest_1   3||Nearest_2   3
Numerator  65||Denominator  25||Result 2.60||Nearest_1   3||Nearest_2   3
Numerator  66||Denominator  25||Result 2.64||Nearest_1   3||Nearest_2   3
Numerator  67||Denominator  25||Result 2.68||Nearest_1   3||Nearest_2   3
Numerator  68||Denominator  25||Result 2.72||Nearest_1   3||Nearest_2   3
Numerator  69||Denominator  25||Result 2.76||Nearest_1   3||Nearest_2   3
Numerator  70||Denominator  25||Result 2.80||Nearest_1   3||Nearest_2   3
Numerator  71||Denominator  25||Result 2.84||Nearest_1   3||Nearest_2   3
Numerator  72||Denominator  25||Result 2.88||Nearest_1   3||Nearest_2   3
Numerator  73||Denominator  25||Result 2.92||Nearest_1   3||Nearest_2   3
Numerator  74||Denominator  25||Result 2.96||Nearest_1   3||Nearest_2   3
*/
2.Signed Integers

The formulas described above cannot apply to signed integers when the denominator and numerator are of different signs (one is positive and the other one is negative or vice-versa). For computing the nearest integer after division you can use the following functions:
/*
 * Description:
 *  Returns the rounded result of the division
 * Parameters:
 *  numerator - the numerator
 *  denominator - the denominator
 * Returns:
 *  The nearest integer of the result
 */
int Round_Division1(int numerator, int denominator)
{
    int result;

    if( ( (numerator > 0) && (denominator < 0) ) ||
        ( (numerator < 0) && (denominator > 0) ) )
    {
        result = (int) ( (double)(numerator) / (double)(denominator) + 0.5);
    }
    else
    {
        result = (int) ( (double)(numerator) / (double)(denominator) - 0.5);
    }
    return result;
}
/*
 * Description:
 *  Returns the rounded result of the division
 * Parameters:
 *  numerator - the numerator
 *  denominator - the denominator
 * Returns:
 *  The nearest integer of the result
 */
int Round_Division2(int numerator, int denominator)
{
    int result;

    if( ( (numerator > 0) && (denominator < 0) ) ||
        ( (numerator < 0) && (denominator > 0) ) )
    {
        result = ( numerator - (denominator/2) ) / denominator;
    }
    else
    {
        result = ( numerator + (denominator/2 )) / denominator;
    }
    return result;
}
Example:
#include<stdio.h>

int Round_Division1(int numerator, int denominator);
int Round_Division2(int numerator, int denominator);

int main(void)
{
    int numerator   = -50;
    int denominator = 25;
    int iResult1;
    int iResult2;
    double fResult;
    int i;

    for(i = 0; i < 25; i++)
    {
        fResult = (double)(numerator)/(double)(denominator);
        iResult1 = Round_Division1(numerator,denominator);
        iResult2 = Round_Division2(numerator,denominator);
        printf("Numerator %3d||Denominator %3d||Result %3.2f||"
                "Nearest_1 %3d||Nearest_2 %3d\n",
                numerator, denominator, fResult, iResult1, iResult2);
        numerator++;
    }
    return 0;
}
/*Output:
Numerator -50||Denominator  25||Result -2.00||Nearest_1  -2||Nearest_2  -2
Numerator -49||Denominator  25||Result -1.96||Nearest_1  -2||Nearest_2  -2
Numerator -48||Denominator  25||Result -1.92||Nearest_1  -2||Nearest_2  -2
Numerator -47||Denominator  25||Result -1.88||Nearest_1  -2||Nearest_2  -2
Numerator -46||Denominator  25||Result -1.84||Nearest_1  -2||Nearest_2  -2
Numerator -45||Denominator  25||Result -1.80||Nearest_1  -2||Nearest_2  -2
Numerator -44||Denominator  25||Result -1.76||Nearest_1  -2||Nearest_2  -2
Numerator -43||Denominator  25||Result -1.72||Nearest_1  -2||Nearest_2  -2
Numerator -42||Denominator  25||Result -1.68||Nearest_1  -2||Nearest_2  -2
Numerator -41||Denominator  25||Result -1.64||Nearest_1  -2||Nearest_2  -2
Numerator -40||Denominator  25||Result -1.60||Nearest_1  -2||Nearest_2  -2
Numerator -39||Denominator  25||Result -1.56||Nearest_1  -2||Nearest_2  -2
Numerator -38||Denominator  25||Result -1.52||Nearest_1  -2||Nearest_2  -2
Numerator -37||Denominator  25||Result -1.48||Nearest_1  -1||Nearest_2  -1
Numerator -36||Denominator  25||Result -1.44||Nearest_1  -1||Nearest_2  -1
Numerator -35||Denominator  25||Result -1.40||Nearest_1  -1||Nearest_2  -1
Numerator -34||Denominator  25||Result -1.36||Nearest_1  -1||Nearest_2  -1
Numerator -33||Denominator  25||Result -1.32||Nearest_1  -1||Nearest_2  -1
Numerator -32||Denominator  25||Result -1.28||Nearest_1  -1||Nearest_2  -1
Numerator -31||Denominator  25||Result -1.24||Nearest_1  -1||Nearest_2  -1
Numerator -30||Denominator  25||Result -1.20||Nearest_1  -1||Nearest_2  -1
Numerator -29||Denominator  25||Result -1.16||Nearest_1  -1||Nearest_2  -1
Numerator -28||Denominator  25||Result -1.12||Nearest_1  -1||Nearest_2  -1
Numerator -27||Denominator  25||Result -1.08||Nearest_1  -1||Nearest_2  -1
Numerator -26||Denominator  25||Result -1.04||Nearest_1  -1||Nearest_2  -1
*/

No comments:

Post a Comment

Got a question regarding something in the article? Leave me a comment and I will get back at you as soon as I can!

Related Posts Plugin for WordPress, Blogger...
Recommended Post Slide Out For Blogger