45

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

尽管:

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

为了:

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

但是哪个更快?

4

17 回答 17

28

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

也就是说,从理论上讲,如果速度更快,任何理智的实现都可能能够实现另一个,因此差异最多可以忽略不计。

当然,我假设whilefor表现得像他们在 C 和类似语言中所做的那样。您可以创建一种具有完全不同语义的while语言for

于 2010-09-02T16:35:19.697 回答
14

在 C# 中,For 循环稍微快一些。

对于循环平均约 2.95 到 3.02 毫秒。

While 循环的平均时间约为 3.05 到 3.37 毫秒。

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

 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");
        }
    }
于 2010-09-02T17:01:26.267 回答
12

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

var i = myArray.length;
while(i--){
  // Do something
}
于 2010-09-02T16:48:27.407 回答
5

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

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

于 2010-09-02T16:43:20.967 回答
3

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

于 2010-09-02T16:37:44.983 回答
3

我在可靠的测试机器上使用了 for 和 while 循环(没有运行非标准的第 3 方后台进程)。我运行了一个for loopvswhile loop因为它与更改 10,000 个<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

这是演示链接

更新

下面是我进行的一个单独测试,它实现了 2 种不同编写的阶乘算法,一种使用 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

结论:无论测试的样本大小或特定的任务类型,在 while 和 for 循环之间的性能方面都没有明显的赢家。在 MacAir 上使用 OS X Mavericks 在 Chrome 常青树上进行测试。

于 2015-07-19T17:25:14.713 回答
3

至于无限循环,for(;;)循环比每次评估条件时都要好while(1)while但它又取决于编译器。

于 2017-07-17T20:10:34.690 回答
2

将循环迭代设置为 10,000。

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

对两种代码都这样做,任何一个具有最低毫秒的运行速度更快。您可能希望多次运行测试并将它们平均以减少后台进程影响测试的可能性。

你很可能在他们两个上得到非常相似的时间,但我很想看看一个是否总是稍微快一点。

于 2010-09-02T16:40:50.423 回答
1

一些优化编译器将能够使用 for 循环进行更好的循环展开,但很可能,如果你正在做一些可以展开的事情,那么一个足够聪明的编译器可以展开它可能也足够聪明来解释你的循环条件while 循环也可以展开。

于 2010-09-02T17:07:47.540 回答
0

他们应该是平等的。您编写的 for 循环与 while 循环所做的事情完全相同:在循环结束时设置$i=0、打印$i和递增$i

于 2010-09-02T16:36:45.593 回答
0

这将取决于所述循环的语言实现、编译器等等。

大多数编译器将编译为完全相同的可执行代码,例如他们肯定会在 CIL (.NET) 中编译。

来源:vcsjones@ http ://forums.asp.net/t/1041090.aspx

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

于 2010-09-02T16:40:24.917 回答
0

我想知道同样的事情,所以我用谷歌搜索并最终来到了这里。我在 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 微秒

尽管:

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 微秒

于 2015-02-24T11:07:13.830 回答
0

我还尝试在 C# 中对不同类型的循环进行基准测试。我使用了与 Shane 相同的代码,但我也尝试了 do-while 并发现它是最快的。这是代码:

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");
    }
}

这些是DotNetFiddle 上的现场演示的结果:

执行 While 循环:
00:00:00.06

While 循环:
00:00:00.13

循环:
00:00:00.27

于 2018-05-22T11:57:57.403 回答
0

for 循环比使用 OpenMP 之类的 while 循环更容易并行化

因此,如果循环内的代码足够耗时,则 for 循环并将其并行化。

对于简短的代码片段,您不希望并行化,因为启动另一个线程(一项昂贵的操作)比简单地完成循环需要更长的时间。所以从另一个来看,任何一个似乎都差不多答案。

于 2021-06-20T21:18:21.433 回答
-1

取决于语言,很可能是它的编译器,但它们在大多数语言中应该是等价的。

于 2010-09-02T16:35:20.667 回答
-1

哪个更快并不重要。如果它确实重要,那么使用您的真实代码对其进行基准测试并亲自查看。

这个其他问题的答案也可能有用:如何编写更有效的代码

于 2010-09-02T16:37:48.523 回答
-1

从技术上讲,For 循环不是 Do While 吗?

例如

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

将会...

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

虽然我可能是错的......

当涉及到 for 循环时。如果您打算只检索数据而不修改数据,则应使用 foreach。如果出于某种原因需要实际索引,则需要递增,因此应使用常规 for 循环。

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

应该比...快

for (int i = 0; i < data.length; ++i)
{
      data[i].doSomething();
}
于 2013-01-09T19:07:09.563 回答