С быстрым расчетом следующего кратного 4? - PullRequest
19 голосов
/ 07 января 2010

Какой быстрый способ округлить число без знака int до кратного 4?

Кратное число 4 имеет два младших значащих бита 0, верно? Таким образом, я мог бы замаскировать их и затем выполнить оператор switch, добавив 1,2 или 3 к заданному uint.

Это не очень элегантное решение ..

Есть также арифметический обзор:

 myint == 0 ? 0 : ((myint+3)/4)*4

Возможно, есть лучший способ, включающий некоторые битовые операции?

Ответы [ 7 ]

41 голосов
/ 07 января 2010
(myint + 3) & ~0x03

Добавление 3 так, что следующее кратное 4 становится предыдущим кратным 4, которое получается с помощью операции по модулю, выполнимой путем маскирования, поскольку делитель имеет степень 2.

15 голосов
/ 07 января 2010

Я предполагаю, что вы пытаетесь достичь выравнивания входного числа, то есть, если исходное число уже кратно 4, его не нужно менять. Однако это не ясно из вашего вопроса. Может быть, вы хотите следующий кратный, даже если исходный номер уже кратен? Пожалуйста, уточните.

Чтобы выровнять произвольное неотрицательное число i по произвольной границе n, вам просто нужно сделать

i = i / n * n;

Но это выровняет его к отрицательной бесконечности. Чтобы выровнять его по положительной бесконечности, добавьте n - 1 перед выполнением выравнивания

i = (i + n - 1) / n * n;

Это уже достаточно для всех целей и задач. В вашем случае это будет

i = (i + 3) / 4 * 4;

Однако, если вы предпочитаете выжимать из этого несколько тактовых частот процессора, вы можете использовать тот факт, что i / 4 * 4 можно заменить на немного-тиддлинг i & ~0x3, что даст вам

i = (i + 3) & ~0x3;

хотя меня не удивило бы, если бы современные компиляторы могли выяснить последнее самостоятельно.

4 голосов
/ 07 января 2010

Если под «следующим кратным 4» вы подразумеваете наименьшее кратное 4, которое больше, чем ваше целое число без знака myint, то это будет работать:

(myint | 0x03) + 1;
1 голос
/ 07 января 2010

(myint + 4) & 0xFFFC

0 голосов
/ 14 марта 2017

Это не ветвление, обычно настраиваемое, простое для понимания (если вы знаете о байтовых строках C), и оно позволяет вам не думать о размере бит myInt:

myInt += "\x00\x03\x02\x01"[myInt & 0x3];

Единственным недостатком является возможный единый доступ к памяти в другом месте (статическое хранение строк), чем в стеке.

0 голосов
/ 07 января 2010

myint = (myint + 4) & 0xffffffc

Это предполагает, что «следующим кратным 4» вы всегда движетесь вверх; то есть 5 -> 8 и 4 -> 8.

0 голосов
/ 07 января 2010

Если вы хотите, чтобы следующий кратный 4 был строго больше myint, это решение подойдет (аналогично предыдущим сообщениям):

(myint + 4) & ~3u

Если вместо этого вы хотите округлить до ближайшего кратного 4 (оставив myint без изменений, если равно , кратному 4), это должно сработать:

(0 == myint & 0x3) ? myint : ((myint + 4) & ~3u);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...