Я не уверен, что вы там рассчитываете, если честно. Вы говорите о работе по модулю, но обычно операция по модулю находится между двумя числами a
и b
, и ее результатом является остаток от деления a
на b
. Где в вашем псевдокоде a
и b
...?
В любом случае, может быть, это поможет: a mod b = a - floor(a / b) * b
.
Я не знаю, быстрее это или нет, это зависит от того, можете ли вы делить и умножать быстрее, чем много вычитаний.
Еще один способ ускорить вычитание - использовать бинарный поиск. Если вы хотите a mod b
, вам нужно вычесть b
из a
до тех пор, пока a
не станет меньше b
. Так что в основном вам нужно найти k
такой, что:
a - k*b < b, k is min
Один из способов найти это k
- это линейный поиск:
k = 0;
while ( a - k*b >= b )
++k;
return a - k*b;
Но вы также можете выполнить бинарный поиск (только несколько тестов, но они работали на всех):
k = 0;
left = 0, right = a
while ( left < right )
{
m = (left + right) / 2;
if ( a - m*b >= b )
left = m + 1;
else
right = m;
}
return a - left*b;
Я предполагаю, что решение для двоичного поиска будет самым быстрым при работе с большими числами.
Если вы хотите вычислить a mod b
и только a
- это большое число (вы можете хранить b
для примитивного типа данных), вы можете сделать это еще быстрее:
for each digit p of a do
mod = (mod * 10 + p) % b
return mod
Это работает, потому что мы можем написать a
как a_n*10^n + a_(n-1)*10^(n-1) + ... + a_1*10^0 = (((a_n * 10 + a_(n-1)) * 10 + a_(n-2)) * 10 + ...
Я думаю, что бинарный поиск - это то, что вы ищете.