代码之家  ›  专栏  ›  技术社区  ›  Mark Lalor

哪一个循环更快?

  •  29
  • Mark Lalor  · 技术社区  · 14 年前

    您可以使用for和while循环获得相同的输出:

    而:

    $i = 0;
    while ($i <= 10){
      print $i."\n";
      $i++;
    };
    

    为:

    for ($i = 0; $i <= 10; $i++){
      print $i."\n";
    }
    

    但哪一个更快?

    16 回复  |  直到 6 年前
        1
  •  21
  •   Mehrdad Afshari    14 年前

    这显然取决于特定语言的解释器/编译器的特定实现。

    也就是说,理论上讲,任何理智的执行,如果速度更快的话,都可能实现一个或另一个,所以差异至多可以忽略不计。

    当然,我想 while for 在C语言和类似语言中表现得和他们一样。您可以使用完全不同的语义为 虽然 对于

        2
  •  12
  •   Jéf Bueno    9 年前

    在C语言中, for循环 稍微快一点。

    循环平均约2.95至3.02 ms。

    while循环平均约为3.05至3.37 ms。

    快速小控制台应用程序证明:

     class Program
        {
            static void Main(string[] args)
            {
                int max = 1000000000;
                Stopwatch stopWatch = new Stopwatch();
    
                if (args.Length == 1 && args[0].ToString() == "While")
                {
                    Console.WriteLine("While Loop: ");
                    stopWatch.Start();
                    WhileLoop(max);
                    stopWatch.Stop();
                    DisplayElapsedTime(stopWatch.Elapsed);
                }
                else
                {
                    Console.WriteLine("For Loop: ");
                    stopWatch.Start();
                    ForLoop(max);
                    stopWatch.Stop();
                    DisplayElapsedTime(stopWatch.Elapsed);
                }
            }
    
            private static void WhileLoop(int max)
            {
                int i = 0;
                while (i <= max)
                {
                    //Console.WriteLine(i);
                    i++;
                };
            }
    
            private static void ForLoop(int max)
            {
                for (int i = 0; i <= max; i++)
                {
                    //Console.WriteLine(i);
                }
            }
    
            private static void DisplayElapsedTime(TimeSpan ts)
            {
                // Format and display the TimeSpan value.
                string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                    ts.Hours, ts.Minutes, ts.Seconds,
                    ts.Milliseconds / 10);
                Console.WriteLine(elapsedTime, "RunTime");
            }
        }
    
        3
  •  6
  •   Lingasamy Sakthivel Subodh    9 年前

    我发现最快的循环是反向while循环,例如:

    var i = myArray.length;
    while(i--){
      // Do something
    }
    
        4
  •  4
  •   Aillyn    14 年前

    正如其他人所说,任何值得一试的编译器都会生成几乎相同的代码。性能上的任何差异都可以忽略不计-您正在进行微优化。

    真正的问题是,什么更具可读性?这就是 for 循环(至少imho)。

        5
  •  3
  •   nmichaels    14 年前

    如果那是一个C程序,我也不会说。编译器将输出完全相同的代码。因为它不是,我说测量它。实际上,这与哪一个循环结构更快无关,因为这样可以节省很小的时间。关于哪个循环结构更容易维护。在您展示的例子中,for循环更合适,因为它是其他程序员(希望包括未来的您)希望看到的。

        6
  •  3
  •   AttackingHobo    14 年前

    将循环迭代设置为10000。

    以毫秒为单位查找时间>运行循环>以毫秒为单位查找时间并减去第一个计时器。

    对这两个代码都这样做,有史以来最短的毫秒,它运行得更快。您可能希望多次运行测试,并将其平均化,以降低后台进程影响测试的可能性。

    你很可能在这两个方面都会得到相似的时间,但我有兴趣看看一个总是稍微快一点。

        7
  •  1
  •   murgatroid99 dhg    14 年前

    他们应该是平等的。您编写的for循环与while循环执行的操作完全相同:设置 $i=0 印刷 $i ,并递增 我一美元 在循环的末尾。

        8
  •  1
  •   Chris    14 年前

    一些优化的编译器可以用for循环更好地展开循环,但很可能的情况是,如果您正在执行一些可以展开的操作,那么一个足够智能的编译器展开它,也可能足够智能,可以将while循环的循环条件解释为它也可以展开的操作。

        9
  •  1
  •   AlphaG33k    9 年前

    我在一台固态测试机上使用了for和while循环(没有运行非标准的第三方后台进程)。我跑了一个 for loop VS while loop 因为它与更改10000的Style属性有关 <button> 节点。

    测试连续运行10次,1次运行在执行前超时1500毫秒:

    这是我为这个目的制作的非常简单的javascript

    function runPerfTest() {
        "use strict";
    
        function perfTest(fn, ns) {
            console.time(ns);
            fn();
            console.timeEnd(ns);
        }
    
        var target = document.getElementsByTagName('button');
    
        function whileDisplayNone() {
            var x = 0;
            while (target.length > x) {
                target[x].style.display = 'none';
                x++;
            }
        }
    
        function forLoopDisplayNone() {
            for (var i = 0; i < target.length; i++) {
                target[i].style.display = 'none';
            }
        }
    
        function reset() {
            for (var i = 0; i < target.length; i++) {
                target[i].style.display = 'inline-block';
            }
        }
    
        perfTest(function() {
            whileDisplayNone();
        }, 'whileDisplayNone');
    
        reset();
    
        perfTest(function() {
            forLoopDisplayNone();
        }, 'forLoopDisplayNone');
    
        reset();
    };
    
    $(function(){
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        setTimeout(function(){
            console.log('cool run');
            runPerfTest();
        }, 1500);
    });
    

    这是我得到的结果

    pen.js:8 whileDisplayNone: 36.987ms
    pen.js:8 forLoopDisplayNone: 20.825ms
    
    pen.js:8 whileDisplayNone: 19.072ms
    pen.js:8 forLoopDisplayNone: 25.701ms
    
    pen.js:8 whileDisplayNone: 21.534ms
    pen.js:8 forLoopDisplayNone: 22.570ms
    
    pen.js:8 whileDisplayNone: 16.339ms
    pen.js:8 forLoopDisplayNone: 21.083ms
    
    pen.js:8 whileDisplayNone: 16.971ms
    pen.js:8 forLoopDisplayNone: 16.394ms
    
    pen.js:8 whileDisplayNone: 15.734ms
    pen.js:8 forLoopDisplayNone: 21.363ms
    
    pen.js:8 whileDisplayNone: 18.682ms
    pen.js:8 forLoopDisplayNone: 18.206ms
    
    pen.js:8 whileDisplayNone: 19.371ms
    pen.js:8 forLoopDisplayNone: 17.401ms
    
    pen.js:8 whileDisplayNone: 26.123ms
    pen.js:8 forLoopDisplayNone: 19.004ms
    
    pen.js:61 cool run
    pen.js:8 whileDisplayNone: 20.315ms
    pen.js:8 forLoopDisplayNone: 17.462ms
    

    这里是 demo link

    更新

    下面是我进行的一个单独的测试,它实现了两种不同的阶乘算法,一种使用for循环,另一种使用while循环。

    代码如下:

    function runPerfTest() {
        "use strict";
    
        function perfTest(fn, ns) {
            console.time(ns);
            fn();
            console.timeEnd(ns);
        }
    
        function whileFactorial(num) {
            if (num < 0) {
                return -1;
            }
            else if (num === 0) {
                return 1;
            }
            var factl = num;
            while (num-- > 2) {
                factl *= num;
            }
            return factl;
        }
    
        function forFactorial(num) {
            var factl = 1;
            for (var cur = 1; cur <= num; cur++) {
                factl *= cur;
            }
            return factl;
        }
    
        perfTest(function(){
            console.log('Result (100000):'+forFactorial(80));
        }, 'forFactorial100');
    
        perfTest(function(){
            console.log('Result (100000):'+whileFactorial(80));
        }, 'whileFactorial100');
    };
    
    (function(){
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        runPerfTest();
        console.log('cold run @1500ms timeout:');
        setTimeout(runPerfTest, 1500);
    })();
    

    阶乘基准的结果是:

    pen.js:41 Result (100000):7.15694570462638e+118
    pen.js:8 whileFactorial100: 0.280ms
    pen.js:38 Result (100000):7.156945704626378e+118
    pen.js:8 forFactorial100: 0.241ms
    pen.js:41 Result (100000):7.15694570462638e+118
    pen.js:8 whileFactorial100: 0.254ms
    pen.js:38 Result (100000):7.156945704626378e+118
    pen.js:8 forFactorial100: 0.254ms
    pen.js:41 Result (100000):7.15694570462638e+118
    pen.js:8 whileFactorial100: 0.285ms
    pen.js:38 Result (100000):7.156945704626378e+118
    pen.js:8 forFactorial100: 0.294ms
    pen.js:41 Result (100000):7.15694570462638e+118
    pen.js:8 whileFactorial100: 0.181ms
    pen.js:38 Result (100000):7.156945704626378e+118
    pen.js:8 forFactorial100: 0.172ms
    pen.js:41 Result (100000):7.15694570462638e+118
    pen.js:8 whileFactorial100: 0.195ms
    pen.js:38 Result (100000):7.156945704626378e+118
    pen.js:8 forFactorial100: 0.279ms
    pen.js:41 Result (100000):7.15694570462638e+118
    pen.js:8 whileFactorial100: 0.185ms
    pen.js:55 cold run @1500ms timeout:
    pen.js:38 Result (100000):7.156945704626378e+118
    pen.js:8 forFactorial100: 0.404ms
    pen.js:41 Result (100000):7.15694570462638e+118
    pen.js:8 whileFactorial100: 0.314ms
    

    结论:无论是样本量还是测试的具体任务类型,在一段时间内和for循环之间都没有明确的胜利者。在Macair和OS X Mavericks上对Chrome Evergreen进行测试。

        10
  •  0
  •   Randolpho    14 年前

    取决于语言及其编译器,但在大多数语言中它们应该是等效的。

        11
  •  0
  •   Community datashaman    7 年前

    哪种速度更快不重要。如果真的很重要,那么使用真正的代码对其进行基准测试,并亲自查看。

    其他问题的答案可能也很有用: How to write more efficient code

        12
  •  0
  •   jfrobishow    14 年前

    这将取决于所述循环的语言实现、编译器以及其他功能。

    大多数编译器将编译成完全相同的可执行代码,例如CIL(.net)中的代码。

    资料来源:VCSjones@ http://forums.asp.net/t/1041090.aspx

    不管是哪种方式,循环体都是处理时间将花费的地方,而不是迭代的方式。

        13
  •  0
  •   Jeremy Trifilo    12 年前

    从技术上讲,for循环不是一段时间吗?

    例如。

    for (int i = 0; i < length; ++i)
    {
       //Code Here.
    }
    

    将是…

    int i = 0;
    do 
    {
      //Code Here.
    } while (++i < length);
    

    但我可能错了…

    当涉及到循环时。如果您计划只检索数据而从不修改数据,那么应该使用foreach。如果出于某种原因需要实际的索引,则需要递增,因此应该使用正则for循环。

    for (Data d : data)
    {
           d.doSomething();
    }
    

    应该比…

    for (int i = 0; i < data.length; ++i)
    {
          data[i].doSomething();
    }
    
        14
  •  0
  •   Niclas Lindgren    9 年前

    我也在想同样的事情,所以我在谷歌上搜索了一下,结果来到了这里。 我在python中做了一个小测试(非常简单),只是为了看看,这就是我得到的:

    为:

    def for_func(n = 0):
        for n in range(500):
            n = n + 1
    

    python-m timeit“import for_func;for_func.for_func()”>for_func.txt

    10000个回路,每回路最好3个:40.5 usec

    而:

    def while_func(n = 0):
        while n < 500:
            n = n + 1
    

    python-m timeit“import while_func;while_func.while_func()”>while_func.txt

    10000个回路,每个回路最多3:45个

        15
  •  0
  •   Ilian Zapryanov    7 年前

    至于无限循环 for(;;) 循环比 while(1) 自从 while 每次对条件进行计算,但同样取决于编译器。

        16
  •  0
  •   Fabio says Reinstate Monica MoMoTaur    6 年前

    我还尝试在C中对不同类型的循环进行基准测试。我用过 the same code as Shane 但是我也试了一下,发现它是最快的。这是代码:

    using System;
    using System.Diagnostics;
    
    
    public class Program
    {
        public static void Main()
        {
            int max = 9999999;
            Stopwatch stopWatch = new Stopwatch();
    
            Console.WriteLine("Do While Loop: ");
            stopWatch.Start();
            DoWhileLoop(max);
            stopWatch.Stop();
            DisplayElapsedTime(stopWatch.Elapsed);
            Console.WriteLine("");
            Console.WriteLine("");
    
            Console.WriteLine("While Loop: ");
            stopWatch.Start();
            WhileLoop(max);
            stopWatch.Stop();
            DisplayElapsedTime(stopWatch.Elapsed);
            Console.WriteLine("");
            Console.WriteLine("");
    
            Console.WriteLine("For Loop: ");
            stopWatch.Start();
            ForLoop(max);
            stopWatch.Stop();
            DisplayElapsedTime(stopWatch.Elapsed);
        }
    
        private static void DoWhileLoop(int max)
        {
            int i = 0;
            do
            {
                //Performe Some Operation. By removing Speed increases
                var j = 10 + 10;
                j += 25;
                i++;
            } while (i <= max);
        }
    
        private static void WhileLoop(int max)
        {
            int i = 0;
            while (i <= max)
            {
                //Performe Some Operation. By removing Speed increases
                var j = 10 + 10;
                j += 25;
                i++;
            };
        }
    
        private static void ForLoop(int max)
        {
            for (int i = 0; i <= max; i++)
            {
                //Performe Some Operation. By removing Speed increases
                var j = 10 + 10;
                j += 25;
            }
        }
    
        private static void DisplayElapsedTime(TimeSpan ts)
        {
            string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
            Console.WriteLine(elapsedTime, "RunTime");
        }
    }
    

    这些是 live demo on DotNetFiddle :

    做while循环:
    00∶00:0.06

    循环时:
    00∶00:0.13

    for循环:
    00∶00:0.27