Ответ 1
(myint + 3) & ~0x03
Добавление 3 состоит в том, что следующий кратный 4 становится прежним кратным 4, который создается по модулю, выполнимым путем маскировки, поскольку делитель является степенью 2.
Какой быстрый способ округлить unsigned int
до кратного 4
?
У кратного 4 есть два младших значащих бита 0, правильно? Поэтому я мог бы маскировать их, а затем делать оператор switch, добавляя либо 1,2, либо 3 к данному uint
.
Это не очень изящное решение.
Там также арифметическое округление:
myint == 0 ? 0 : ((myint+3)/4)*4
Возможно, есть лучший способ, включая некоторые операции с битами?
(myint + 3) & ~0x03
Добавление 3 состоит в том, что следующий кратный 4 становится прежним кратным 4, который создается по модулю, выполнимым путем маскировки, поскольку делитель является степенью 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;
хотя меня не удивило бы, если бы современные компиляторы могли сами выяснить последние.
Если "next multiple of 4" означает наименьшее кратное 4, которое больше вашего значения unsigned int myint, тогда это будет работать:
(myint | 0x03) + 1;
(myint + 4) и 0xFFFC
Если вы хотите, чтобы следующий кратный 4 был строго больше myint
, это решение будет делать (аналогично предыдущим сообщениям):
(myint + 4) & ~3u
Если вы хотите округлить до ближайшего кратного 4 (оставляя myint
неизменным, если оно кратно 4), это должно работать:
(0 == myint & 0x3) ? myint : ((myint + 4) & ~3u);
Это не зависит от ветки, обычно настраивается, легко понимается (если вы знаете о байтовых строках C), и это позволяет вам не думать о размере бита myInt:
myInt += "\x00\x03\x02\x01"[myInt & 0x3];
Единственный недостаток - это возможный доступ к одной памяти в другом месте (статическое хранилище строк), чем стек.
myint = (myint + 4) и 0xffffffc
Это предполагает, что "следующим кратным 4", что вы всегда двигаетесь вверх; т.е. 5 → 8 и 4 → 8.