Как разделить целое число без знака 256 и округлить до более близкого значения?

Мне нужно разделить число 256 и округлить его до более близкого значения, например, если на входе 255 я хочу получить 1, а не 0. Теперь я использую

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

Но я думаю, что это не оптимальный способ достижения моей цели, может кто-то посоветует лучший способ.

6

Решение

Использовать этот:

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

128 — среднее значение, так что после добавления округления, и 256=2^8 так что вы можете использовать операцию сдвига бит вместо деления.

НОТА: этот способ работает только для положительных ценностей.

Если вам нужно это для положительных и отрицательных значений, вам нужно это:

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

НОТА: сдвиг битов для подписанных значений имеет некоторые особенности и не всегда может быть доверенным, поэтому вы не можете использовать это: int z = (x < 0) ? (x - 128) / 256 : (x + 128) >> 8;

7

Другие решения

Это будет работать как для положительных, так и для отрицательных целых чисел (и нуля тоже):

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

Обязательный -pedantic а также f[oo|ai]lsafe версия:

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;
4

Для правильного округления до ближайшего значения со знаком вы можете сделать это:

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

Для правильной обработки очень больших и малых значений вы можете использовать

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;
}

Или только для неподписанных значений

unsigned int divideAndRound256(unsigned int x)
{
if(x > UINT_MAX - 128)
return ((x - 128) >> 8) + 1;
else
return (x + 128) >> 8;
}
0
По вопросам рекламы [email protected]