C быстрый расчет следующего кратного 4?

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

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

Это не очень изящное решение.

Там также арифметическое округление:

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

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

Ответы

Ответ 1

(myint + 3) & ~0x03

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

Ответ 2

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

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

i = i / n * n;

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

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

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

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

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

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

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

Ответ 3

Если "next multiple of 4" означает наименьшее кратное 4, которое больше вашего значения unsigned int myint, тогда это будет работать:

(myint | 0x03) + 1;

Ответ 4

(myint + 4) и 0xFFFC

Ответ 5

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

(myint + 4) & ~3u

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

(0 == myint & 0x3) ? myint : ((myint + 4) & ~3u);

Ответ 6

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

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

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

Ответ 7

myint = (myint + 4) и 0xffffffc

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