模数运算与三元运算

时间:2013-05-30 20:00:09

标签: c++ c if-statement modulo

我需要迭代n对整数:(0,1),(1,2),(2,3)......(n-2,n-1),(n-1,0)

最好的方法是什么?

  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. 另一个想法?让我们假设有一些做某事的maaaany行,如果我们做(0,1),(1,2),(2,3)...(n-2,n-1)部分,它看起来很难看(n-1,0)部分分开。

  5. 哪种操作效率最高?

    编辑#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秒

         

    Trenary等于:36.684秒

         

    Trenary更大的等于:37.299秒

         

    分为两部分:31.37秒

    所以看来p.s.w.g的想法不仅是最干净的,也是最好的。

    再一次,抱歉我的错误,我不是母语,我还在学习。

1 个答案:

答案 0 :(得分: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'行重构为一个单独的工人类,但不知道更多关于这些行中的内容,很难说。