Это решение без ветвления, но выполняет %
дважды:
function wrapIndex(i, i_max) {
return ((i % i_max) + i_max) % i_max;
}
Следует сказать, что в C#/Java предполагается поведение %
, т.е. результат имеет тот же знак, что и дивиденд. Некоторые языки определяют вычисление остатка с учетом знака делителя (например, mod
в Clojure). Некоторые языки имеют оба варианта (пара mod
/rem
в Common Lisp, Haskell и т.д.). В Алголе-68 есть %x
, который всегда возвращает неотрицательное число. C++ оставил это на усмотрение реализации до C++11, теперь знак остатка (почти) полностью определяется в соответствии со знаком дивиденда.
Лучше дело вкуса, но как насчет
var x = (i_max + i % i_max) % i_max;
Вы можете сделать это:
function wrapIndex(i, i_max) {
if (i < 0) i = (i % i_max) + i_max;
return i % i_max;
}
Многие пользователи дали хорошие ответы, только остерегайтесь отрицательных чисел, так как разные языки может вести себя по-разному. Например, этот фрагмент C пишет «-1»
int main ()
{
printf("%d\n", (-4) % 3);
}
В то время как в python у нас другое выходное значение
Python 2.6.4 (r264:75706, Dec 7 2009, 18:43:55)
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> (-4) % 3
2
EDIT : На самом деле я не думаю, что у вас будут отрицательные индексы! Однако это хорошо знать.
Решение с двумя операциями %
работает, но это несколько быстрее в большинстве языков на большинстве аппаратных средств (есть исключения, однако):
int wrapIndex(int i, int i_max) {
i = i%i_max;
return i<0 ? i+i_max : i;
}