Модулю отрицательных чисел
Возможный дубликат:
Мод отрицательного числа тает мой мозг!
Мне было интересно, был ли более хороший алгоритм для того, что я пытаюсь сделать:
wrapIndex(-6, 3) = 0
wrapIndex(-5, 3) = 1
wrapIndex(-4, 3) = 2
wrapIndex(-3, 3) = 0
wrapIndex(-2, 3) = 1
wrapIndex(-1, 3) = 2
wrapIndex(0, 3) = 0
wrapIndex(1, 3) = 1
wrapIndex(2, 3) = 2
wrapIndex(3, 3) = 0
wrapIndex(4, 3) = 1
wrapIndex(5, 3) = 2
Я придумал
function wrapIndex(i, i_max) {
if(i > -1)
return i%i_max;
var x = i_max + i%i_max;
if(x == i_max)
return 0;
return x;
}
Есть ли лучший способ сделать это?
Ответы
Ответ 1
Это решение является ветвящимся, но выполняет %
дважды:
function wrapIndex(i, i_max) {
return ((i % i_max) + i_max) % i_max;
}
Следует сказать, что предполагается поведение С#/Java %
, т.е. результат имеет тот же знак, что и дивиденд. Некоторые языки определяют вычисление остатка, чтобы вместо этого принять знак делителя (например, mod
в Clojure). Некоторые языки имеют оба варианта (пара mod
/rem
в Common Lisp, Haskell и т.д.). Алгол-68 имеет %x
, который всегда возвращает неотрицательное число. С++ оставил его до реализации до тех пор, пока С++ 11, теперь знак остатка (почти) полностью определен в соответствии с знаком дивиденда.
См. также
Ответ 2
Решение с двумя операциями %
работает, но это немного быстрее в большинстве языков на большинстве аппаратных средств (есть исключения, однако):
int wrapIndex(int i, int i_max) {
i = i%i_max;
return i<0 ? i+i_max : i;
}
Ответ 3
Никер - это вопрос вкуса, но как насчет
var x = (i_max + i % i_max) % i_max;
Ответ 4
Вы можете сделать это:
function wrapIndex(i, i_max) {
if (i < 0) i = (i % i_max) + i_max;
return i % i_max;
}
Ответ 5
Многие пользователи дали хорошие ответы, просто остерегайтесь отрицательных чисел, поскольку разные языки могут вести себя по-разному.
Например, этот фрагмент 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: На самом деле я не думаю, что у вас будут отрицательные индексы! Однако это хорошо знать.