Быстрый модуль 3 или алгоритм деления?

есть ли быстрый алгоритм, подобный мощности 2, который можно использовать с 3, т. е. n%3. Возможно, что-то, что использует тот факт, что если сумма цифр делится на три, то число тоже делится.

Это приводит к следующему вопросу. Каков быстрый способ добавления цифр в число? I. e. 37 -> 3 +7 -> 10 Я ищу что-то, что не имеет условных обозначений, поскольку они, как правило, препятствуют векторизации

спасибо

3 ответов


4 % 3 == 1, so (4^k * a + b) % 3 == (a + b) % 3. Этот факт можно использовать для оценки x%3 для 32-разрядного x:

x = (x >> 16) + (x & 0xffff);
x = (x >> 10) + (x & 0x3ff);
x = (x >> 6) + (x & 0x3f);
x = (x >> 4) + (x & 0xf);
x = (x >> 2) + (x & 0x3);
x = (x >> 2) + (x & 0x3);
x = (x >> 2) + (x & 0x3);
if (x == 3) x = 0;

(непроверенные - вам может понадобиться еще несколько сокращений.) Это быстрее, чем ваше оборудование может сделать x%3? Если так, то, вероятно, не намного.


этой comp.элемент компиляторов имеет конкретную рекомендацию для вычисления по модулю 3.

альтернативой, особенно если максимальный размер дивиденда является скромным, является умножение на реципрокное 3 Как значение с фиксированной точкой, с достаточным количеством битов точности для обработки максимального размера дивиденда для вычисления частного, а затем вычесть 3 * фактор из дивиденда, чтобы получить остаток. Все эти множители могут быть реализованы с фиксированной последовательностью сдвиги-и-добавляет. Количество инструкций будет зависеть от битового шаблона реципрокного. Это работает довольно хорошо, когда дивиденд max является скромным по размеру.

относительно добавления цифр в число... если вы хотите добавить decimal цифры, вы собираетесь в конечном итоге делать то, что составляет число преобразования в десятичный, что включает в себя деление на 10 где-то. Если вы готовы согласиться на сложение цифр в base2, вы можете сделать это с помощью простого сдвига вправо и добавьте цикл. Различные умные трюки могут быть использованы для этого в кусках n бит, чтобы ускорить его дальше.


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

int num = 12345;
int sum = 0;
while (num) {
    sum += num % 10;
    num /= 10;
}

это работает, потому что 12345 % 10 = 5, 12345 / 10 = 1234 и продолжайте идти, пока num == 0