R语言中,for循环是不是比while更高效?

文摘   2025-01-19 09:08   荷兰  

在我刚开始学习R语言的时候,曾经听到过如下论述:for循环要比while循环计算时间更短,对计算机造成的计算负担更小,同时在循环数目较大时,while可能会使电脑死机,所以我们应该尽量使用for循环

这个想法在英文的R语言环境中似乎是一个common misconception,我当时是通过一个在澳洲念书的博主学到的这个观点。而当我二硕的第一节R语言课的时候,老师就澄清了这个misconception。今天这篇文章,我就带大家一起来看一下在R语言中,for循环和while循环在计算速度上是否有差异,而while循环是否有可能使电脑死机。


我们首先使用microbenchmark来比对如下两个分别使用forwhile循环的操作,它们最终生成的结果都是一样的:

microbenchmark({  vec <- rep(NA,100)  for (i in 1:100){    vec[i] <- i  }},{  vec <- rep(NA,100)  i=1  while (i<=100){    vec[i] <- i    i=i+1  }})

下图是forwhile循环分别所用的时间:

我们主要看mean部分,第一行是for循环平均耗时,第二行是while循环平均耗时。可以看到for循环确实比while循环要快一些,但是注意这里的单位是microsecond(微秒),所以两个100次的循环实际上只相差了100微秒(1=1百万微秒)的时间。

你可能会说,现在只有100次循环,如果你将循环次数增多,那么差距会更大。那么我们现在将循环次数增加到1000000次,结果如何呢?

我们可以看到,结果确实是while更久,这次的单位是millesecond(毫秒),所以具体的差异也就只有0.014秒而已……

总的来说,while循环确实在运行相同任务要比for循环更慢一些,理由也很简单:每一次while循环都要经历一次判断。但我们在上述的对比中也看到,这种差异对我们日常的使用是毫无影响的——因为日常情况下我们的循环次数大都不会超过一千或一万次,二即使经历1百万次循环,其差距也不过0.01秒左右……

所以,在执行相同任务情况下,从计算速度的层面上,我们并没有明确的理由偏爱while或者for,而更应该从任务的具体内容和实现方面来对其进行选择。


接下来我们来讨论在循环次数过大时,while是否更容易让计算机死机。其实我们在上述的代码中已经看到,while能够很好地执行百万次的循环。那么很多人所说的这种情况,是如何发生的呢?我们来看如下代码:

microbenchmark({  vec <- NA  i=1  while (i<=100000){    vec <- c(vec,i)    i=i+1  }})

上述代码还是在做一样的事情,做十万次(稍后会解释为什么只做十万次),不同的是这次我没有提前建立一个空向量,而是每次都给已有向量“附加”一个元素上去。这么做的后果是什么呢?

我们可以看到十万次的循环就已经消耗了85毫秒=85000微秒的时间,而之前一百万次的while循环则只消耗了31毫秒的时间。为何会这样呢?因为在新的做法中,计算机每次都需要读取vec向量,创建新的位置,再赋值相关的元素——vec向量的长度越长,占据的存储空间就越大,每次读取与存储的所需要的时间就会更长。所以这种做法所消耗的时间将随着循环次数指数级增长,这也是我没有做一百万次的原因——我的计算机根本就没有办法在短时间内给出结果……

相反,在先前的做法中,我提前建立了一个相应长度的空向量,所以每次循环计算机都只需要将相应元素填充至向量中即可,大大节省了相应的时间。

这种做法导致的时间暴增并不是while本身的问题,如果你使用for循环,但采用相同的方式,for循环同样面临着相同的问题:

大家可以看到,for循环的时间一样暴增到了57毫秒,而之前一百万次的for循环也只消耗了17毫秒时间……

现在给出我们的结论2并不是while循环导致了计算机死机,而是“不良的”代码写作方式导致了计算机死机,我们需要避免的并不是while循环,而是“不良的”代码写作方式

最后总结一下这篇文章的两个重要信息:

1. for循环的运算速度确实比while循环更快,但其差异在日常的任务表现中几乎可以忽略;

2. 在循环次数过多的情况下,while循环并不会导致计算机死机,不预先建立好空向量的代码写作方式才会导致运行速度暴增,而for循环也同样面临着这样的问题。


PsychoStatisticia
一个统计学研究者的个人天地
 最新文章