Пришло заметить, что при модификации
(mod(x, n))
мы предпочли бы сделать na power of 2. Как это помогает, и это быстрее?
Ваш "вопрос" довольно расплывчатый, но, как вы думаете, это то, что вы ищете?
x & (n-1)
где n
- степень 2. Это даст вам x % n
.
Представить биты:
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
Поскольку бит-мутные операции могут выполняться очень быстро, а операции деления относительно медленные, этот тип модуляции намного быстрее, чем деление.
Команда 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)
Чтобы ответить на вопрос, почему это лучше... mod(x,y)
значительной степени стоит столько же, сколько целочисленное деление. Гораздо больше, чем простая операция AND
(в зависимости от вашего аппаратного подразделения может стоить несколько циклов ЦП).
Немного от темы, но определенно в FPGA (verilog/VHDL), операция AND приводит к использованию гораздо меньшего количества оборудования, чем разделения.
modding степенью 2 является & (побитовым И) оператором.
mod (x, 2 ^ k) = x & U
где U = ((2 ^ k) -1), которая является константой.
в противном случае вам нужно разделить и найти остаток. побитовое И обычно составляет 1 такт, чтобы выполнить, тогда как деление происходит намного медленнее. Детали этого связаны с логической реализацией & против%.