2

(0, 1)、(1, 2)、(2, 3) ... (n-2, n-1)、(n-1, 0) の n 組の整数を反復処理する必要があります。

それを行う最良の方法は何ですか?

  1. モジュロ演算の使用:

    for (int i = 0; i < n; i++){
        int a = i;
        int b = (i + 1)%n
        //MaaaanyLinesOfDoSomethingWithAAndB
    }
    
  2. 三項演算の使用:

    for (int i = 0; i < n; i++){
        int a = i;
        int b = (i + 1 == n ? 0 : i + 1)
        //MaaaanyLinesOfDoSomethingWithAAndB
    }
    
  3. または:

    for (int i = 0; i < n; i++){
        int a = i;
        int b = (i + 1 >= n ? 0 : i + 1)
        //MaaaanyLinesOfDoSomethingWithAAndB
    }
    
  4. 別のアイデア?do something の行が無数にあり、 (0, 1), (1, 2), (2, 3) ... (n-2, n-1) の部分と(n-1, 0) の部分を分けます。

最も効率的な操作はどれですか?

EDIT #1 申し訳ありませんが、質問が適切に行われていないと思います。どちらのオペレーターがより速く動作するかを知りたいと思っていました (たとえば、秒またはクロック ティック)。また、ちょっとした実験を行い、clock() 関数で測定することにしました。これが私のコードです:

#include <time.h>
#include <limits.h>
#include <string>
#include <iostream>
using namespace std;

typedef void (*fun) (int a);

void DoSomething(int i){
    int a = i;
}

void ModuloOperation (int n){
    for (int i = 0; i < n; i++)
        DoSomething((i + 1) % n);
}

void TernaryEqual (int n){
    for (int i = 0; i < n; i++)
        DoSomething(i + 1 == n ? 0 : i + 1);
}

void TernaryBiggerEqual (int n){
    for (int i = 0; i < n; i++)
        DoSomething(i + 1 >= n ? 0 : i + 1);
}

void SplitIntoTwoParts (int n){
    for (int i = 0; i < n - 1; i++)
        DoSomething(i + 1);
    DoSomething(n - 1);
}

int main(){

    const int n = INT_MAX;

    string testNames[] = {
        "Modulo", 
        "Trenary equal", 
        "Trenary bigger equal", 
        "Split into two parts"
    };

    fun tests[] = {
        ModuloOperation, 
        TernaryEqual, 
        TernaryBiggerEqual, 
        SplitIntoTwoParts
    };

    clock_t t;

    for (int i = 0; i < sizeof(testNames)/sizeof(testNames[0]); i++){

        t = clock();
        tests[i](n);
        t = clock() - t;

        cout<<testNames[i]<<": "<<((float)t)/CLOCKS_PER_SEC<<" seconds\n\n";
    }

    return 0;
}

そして、ここに出力があります

モジュロ: 53.867 秒

3 等分: 36.684 秒

トレナリ大イコール: 37.299 秒

2 つの部分に分割: 31.37 秒

したがって、pswg のアイデアは、最もクリーンなアイデアであるだけでなく、最良のアイデアでもあるようです。

繰り返しますが、私の間違いで申し訳ありません。私はネイティブ スピーカーではありません。まだ学習中です。

4

1 に答える 1

8

「maaaany」行を個別に実行すると見苦しくなるとおっしゃいました。上記のオプションはどれも特にきれいではありません。したがって、この醜いロジックをメソッドにカプセル化し、ループ内でより洗練されたコードを使用する方がよいでしょう。

読みやすくするために、おそらくこれを使用します。

for (int i = 0; i < n - 1; i++){
    DoStuff(i, i + 1);
}
DoStuff(n - 1, 0);

// elsewhere
void DoStuff(int a, int b)
{
    //MaaaanyLinesOfDoSomethingWithAAndB
}

「maaaany」行でいくつかのローカル変数を使用する必要があり、それらすべてをDoStuffメソッドに渡したくない場合は、クロージャーの使用を検討することをお勧めしますが、コードの可読性にはほとんど役立ちません。適切な機能分解と同じくらい。このようなもの:

Action<int, int> doStuff = (a, b) =>
{
    //MaaaanyLinesOfDoSomethingWithAAndB
};

for (int i = 0; i < n - 1; i++){
    doStuff(i, i + 1);
}
doStuff(n - 1, 0);

あるいは、「maaaany」行を別のワーカー クラスにリファクタリングする必要があるかもしれませんが、これらの行の内容について詳しく知らなければ、なんとも言えません。

于 2013-05-30T20:15:10.563 に答える