负数的模数

时间:2010-08-05 17:00:49

标签: algorithm math modulo

  

可能重复:
  Mod of negative number is melting my brain!

我想知道是否有一个更好的算法,我正在尝试做什么:

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;
    }

有更好的方法吗?

5 个答案:

答案 0 :(得分:22)

此解决方案无分支,但执行%两次:

function wrapIndex(i, i_max) {
   return ((i % i_max) + i_max) % i_max;
}

应该说假设%的C#/ Java行为,即结果与被除数具有相同的符号。有些语言定义余数计算以取代除数的符号(例如Clojure中的mod)。有些语言在Common Lisp,Haskell等中都有变体(mod / rem对。 Algol-68有%x,它总是返回一个非负数。 C ++将其实现到C ++ 11,now the sign of the remainder is (almost) fully specified according to the dividend sign

另见

答案 1 :(得分:10)

具有两个%操作的解决方案可以正常工作,但在大多数硬件上大多数语言都有所加快(但也有例外):

int wrapIndex(int i, int i_max) {
    i = i%i_max;
    return i<0 ? i+i_max : i;
}

答案 2 :(得分:5)

Nicer是品味的问题,但是怎么样

var x = (i_max + i % i_max) % i_max;

答案 3 :(得分:2)

你可以这样做:

function wrapIndex(i, i_max) {
    if (i < 0) i = (i % i_max) + i_max;
    return i % i_max;
}

答案 4 :(得分:2)

许多用户给出了很好的答案,只要注意负数,因为不同的语言可能表现不同。 例如,这个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

编辑:实际上我认为你不会有负面索引!然而,知道这一点很好。