Question

I need to divide number of 256 and round it to closer value, for example, if input 255 I want to get 1, not 0. Now I'm using

int x = 150;
int z = MulDiv(x, 1, 256);

But I think it is not optimal way to reach my goal, can someone advice better way.

Was it helpful?

Solution

Use this:

unsigned int x = 150;
unsigned int z = (x + 128) >> 8;

128 is middle value, so it after adding this your rounding works, and 256=2^8 so you can use bit shift operation instead of division.

NOTE: this way works for only positive values.

If you need this for positive and negative values you will need this:

int x = -150;
int z = (x >= 0 ? (x + 128) : (x - 128)) / 256;

NOTE: bit-shifting for signed values has some specific and not always can be trusted so you cannot use this: int z = (x < 0) ? (x - 128) / 256 : (x + 128) >> 8;

OTHER TIPS

This will work for both positive and negative integers (and zero too):

int eps = x < 0 ? -128 : 128
int y = (x + eps) / 256;

The obligatory -pedantic and f[oo|ai]lsafe version:

if (x < INT_MIN + 128 || x > INT_MAX - 128) {
    fputs("nasal demons!\n", stderr);
    abort();
}

int eps = x < 0 ? -128 : 128;
int y = (x + eps) / 256;

For correct rounding to nearest of signed values you can do this:

y = (x >= 0 ? (x + 128) : (x - 128)) / 256;

To properly handle extremely large and small values you could use

int divideAndRound256(int x)
{    
    if(x > INT_MAX - 128)
        return (x - 128) / 256 + 1;
    else if(x < INT_MIN + 128)
        return (x + 128) / 256 - 1;
    else if(x < 0)
        return (x - 128) / 256;
    else
        return (x + 128) / 256;
}

Or for just unsigned values

unsigned int divideAndRound256(unsigned int x)
{    
    if(x > UINT_MAX - 128)
        return ((x - 128) >> 8) + 1;
    else
        return (x + 128) >> 8;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top