21

重複の可能性:
負の数の Mod が私の脳を溶かしています!

私がやろうとしていることのためのより良いアルゴリズムがあるかどうか疑問に思っていました:

ラップインデックス (-6, 3) = 0
ラップインデックス (-5, 3) = 1
ラップインデックス (-4, 3) = 2
ラップインデックス (-3, 3) = 0
ラップインデックス (-2, 3) = 1
wrapIndex(-1, 3) = 2
ラップインデックス (0, 3) = 0
ラップインデックス (1, 3) = 1
ラップインデックス (2, 3) = 2
ラップインデックス (3, 3) = 0
ラップインデックス (4, 3) = 1
ラップインデックス (5, 3) = 2

私が思いついた

関数 wrapIndex(i, i_max) {
        if(i > -1)
            i%i_max を返します。

        var x = i_max + i%i_max;
        if(x == i_max)
            0 を返します。

        x を返します。
    }

これを行うより良い方法はありますか?

4

5 に答える 5

28

このソリューションはブランチレスですが、%2 回実行されます。

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

の C#/Java の動作が想定されています。つまり、結果は被除数%と同じ符号を持ちます。一部の言語では、代わりに除数の符号を取る剰余計算が定義されています( Clojure など)。一部の言語には両方のバリアントがあります ( Common Lisp、Haskell などでは/ペア)。Algol-68 には、常に負でない数値を返すものがあります。C++ は C++11 まで実装に任せていましたが、現在では剰余の符号は (ほぼ) 被除数 sign に従って完全に指定されています。modmodrem%x

こちらもご覧ください

于 2010-08-05T17:07:27.690 に答える
10

2 つの操作を使用したソリューションは%機能しますが、ほとんどのハードウェア上のほとんどの言語では、この方法の方が若干高速です (ただし、例外があります)。

int wrapIndex(int i, int i_max) {
    i = i%i_max;
    return i<0 ? i+i_max : i;
}
于 2010-08-05T17:17:18.030 に答える
5

好みの問題ですが、いかがでしょうか?

var x = (i_max + i % i_max) % i_max;
于 2010-08-05T17:05:25.900 に答える
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

編集:実際には、負のインデックスがあるとは思いません! しかし、それを知ることは良いことです。

于 2010-08-05T17:50:47.447 に答える
2

あなたはこれを行うことができます:

function wrapIndex(i, i_max) {
    if (i < 0) i = (i % i_max) + i_max;
    return i % i_max;
}
于 2010-08-05T17:03:35.123 に答える