Низкоуровневая реализация побитового мода

0

Пришло заметить, что при модификации

(mod(x, n))

мы предпочли бы сделать na power of 2. Как это помогает, и это быстрее?

  • 0
    В предложенных ответах используется тот факт, что двоичное представление целочисленного модульного 2 ^ k является только последней частью целого числа, но будьте осторожны, оно работает только с целыми числами без знака и целыми числами со знаком с дополнением 2.
Теги:
modulus
bit-manipulation

5 ответов

4

Ваш "вопрос" довольно расплывчатый, но, как вы думаете, это то, что вы ищете?

x & (n-1)

где n - степень 2. Это даст вам x % n.

2

Представить биты:

Let n = (1000)2 = 8

Поэтому, если вы хотите знать остаток X/n, вам просто нужно знать, есть ли какие-либо значения в 3-х местах ниже мощности 2:

Let X = (1111)2 = 15
          ^^^ .... these will be the remainder

Поэтому, если вы выберете некоторую мощность 2 и вычитаете 1 из нее, вы получите все биты, установленные для чего-либо ниже:

n - 1 = (1000)2 - (0001)2 = (0111)2

Глядя на X сейчас:

  X     = (1111)2
& n - 1 = (0111)2
------------------
        = (0111)2

Поскольку бит-мутные операции могут выполняться очень быстро, а операции деления относительно медленные, этот тип модуляции намного быстрее, чем деление.

0

Команда div в ассемблере (использующая для вычисления мод) намного дороже из команды shift.

обычно: 1 div = 4 смены.

div с силой двух можно заменить сдвигом.

n=2 -> shift by 1,  mod = i & 1  
n=4 -> shift by 2,  mod = i & 3

или вообще для любого int i

n=2^i -> shift by i, mod = x & ((2^i)-1)  
0

Чтобы ответить на вопрос, почему это лучше... mod(x,y) значительной степени стоит столько же, сколько целочисленное деление. Гораздо больше, чем простая операция AND (в зависимости от вашего аппаратного подразделения может стоить несколько циклов ЦП).

Немного от темы, но определенно в FPGA (verilog/VHDL), операция AND приводит к использованию гораздо меньшего количества оборудования, чем разделения.

0

modding степенью 2 является & (побитовым И) оператором.

mod (x, 2 ^ k) = x & U

где U = ((2 ^ k) -1), которая является константой.

в противном случае вам нужно разделить и найти остаток. побитовое И обычно составляет 1 такт, чтобы выполнить, тогда как деление происходит намного медленнее. Детали этого связаны с логической реализацией & против%.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню