【问题标题】:what is the fastest way to get all combinations in a for loop [closed]在for循环中获取所有组合的最快方法是什么[关闭]
【发布时间】:2013-08-26 09:20:03
【问题描述】:

我想得到两个int 元素的所有组合,比如 j 和 i,两者都不应该小于 3,这是我尝试过的:

for (int i =  10; i>=3;i--)
{
   for (int j = 23, j >= 3,j--) 
   {
       std::cout << " the i value " << i 
       << "the j value :" << j << std::endl; // since I'm using those combinations  
                                             // for the rest of my code I wrote 
                                             // this to keep things simple    
   }
}

他们在没有for循环的情况下无论如何都要这样做吗?

【问题讨论】:

  • 您要在这里优化什么?
  • 由于这不是您的真实代码,并且您没有描述您的真实应用程序,我们如何帮助优化您的代码?
  • 是什么让你觉得这还不够快?
  • 不,引擎,我确定不是。需要时间的是您在循环中所做的任何事情。
  • cv::findChessboardCorners() -- 嗯,取 [3..10] 和 [3..23] 的叉积并不是找到棋盘角的好方法。也许如果您更准确地了解您真正想要实现的目标......事实上,这是一个经典的 XY 问题 (meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。

标签: c++ algorithm optimization


【解决方案1】:

这是正确的做法。

您可以使用其他循环,但逻辑始终保持不变。

【讨论】:

    【解决方案2】:

    关于唯一值得尝试的合理变体是预先计算 值,将它们放入静态数组,并使用单个索引 从那里访问它们。仅当值的数量 相当小(如您的示例),即使那样,它也远非 确定它会加快速度。你获得了一次比较(因为 你有一个循环,而不是嵌套循环),但是那个比较 只在外循环和内存访问中执行,尤其是在 现代机器,可能很贵。

    您应该做的第一件事是分析您的代码。如果你在做 任何对循环中的值有意义的东西,它花费的时间 循环代码本身甚至无法测量。不要试图优化 不需要的东西。

    【讨论】:

      【解决方案3】:

      您的方式无疑是最易读且易于维护的方式。

      当然还有其他技巧,但不一定要让代码运行得更快。

      例如,您可以简单地使用 1 级循环:

      //assuming I am getting i [0..5), j [0..7)
      
      for (int x = 0; x < 5*7 ; ++x) {
         cout << "i " << x/7 << " j " << x%7 << endl;
      }
      

      (有点像多维数组使用一维数组的方式,但它并没有使代码更容易或更快。只是为了好玩......:P)

      【讨论】:

      • 它会使代码运行得更慢。运算符/% 非常慢。
      • @Ari 这取决于平台。和常数值。 (但作为一般规则,我希望它会更慢。独立于每个操作的成本,你正在做更多的操作。)
      • 大声笑,是的,事实上我知道这一点,这就是为什么我说这只是为了好玩:P
      【解决方案4】:

      如果你有一个整数列表,你可以把它们放在一个向量中,然后使用 `std::next_permutation' 来遍历可能的排列

      http://en.cppreference.com/w/cpp/algorithm/next_permutation

      【讨论】:

      • 使用 next_permutation 是否更快?
      • @Engine 会慢一些。对于您描述的问题,您的代码几乎尽可能快。
      • @Ari 一旦优化器通过它,它会尽可能快。不只是几乎。
      【解决方案5】:

      我认为这是正确的做法。可能还有其他一些方法可以做到这一点,但这些方法的可读性可能会降低。如果您确实选择了不同的方法,那么请确保您对它进行计时,在没有可衡量的加速的情况下降低代码的可读性是不值得的。

      【讨论】:

        【解决方案6】:

        您需要使用某种循环。你可以稍微优化一下:

        1. 使用++i --i 代替i++i--。它更容易操作,因为i++i-- 返回新值,而不是旧值。

        2. 如果您想遍历二维数组并且迭代顺序无关紧要,最好先遍历j,然后遍历i

          for(int j = 0; j < MAXJ; ++j){
              for(int i = 0; i < MAXI; ++i){
                  do_sth_with(arr[i][j]);
              }
          }
          
        3. 如果您只需要写新行,请不要使用std:endlstd:endl 强制刷新 stdout,因此它比 "\n" 慢。

        【讨论】:

        • Re 1:绝对没有区别。 (我已经测量过。) Re 2:我没有测量过,但除非您将这些值用作大型矩阵的索引(在这种情况下,局部性可能是一个问题),否则这无关紧要。回复3:他说std::cout的输出只是一个例子,所以'\n'std::endl之间的选择是无关紧要的(通常是这种情况)。
        • @JamesKanze 1:取决于系统等等,它可能会有所不同。特别是如果它适用于相同的奇怪环境(即旧/慢 cpu)。 2:对于几 MB 的大型阵列,它会有所不同,在家用 PC 上进行了测试。
        • Re 1:不,没有区别。即使在旧的、缓慢的 CPU 上也是如此。例如,它对 PDP-11 没有任何影响,即使有用于后增量的机器指令,但没有用于预增量的机器指令。两者都生成完全相同的机器代码。至于2:他没有说他用他的价值观做什么。对于相对较大的矩阵,它可能会对现代机器产生影响。然而,他没有说他对这些值做了什么,他使用的值也不是很大。
        猜你喜欢
        • 2021-04-08
        • 1970-01-01
        • 2023-03-29
        • 2021-11-19
        • 2011-07-17
        • 1970-01-01
        • 2017-06-28
        相关资源
        最近更新 更多