[英]Why is while loop much faster than range in this case?
According to this post , range loop should be faster than while loop in python, but please have a look at the following code. 根据这篇文章 ,范围循环应该比python中的while循环更快,但请看下面的代码。 It is simply used to test if a number is prime and return the divisor if n is not a prime.
它仅用于测试数字是否为素数,如果n不是素数则返回除数。
import time
def isPrimeWhile(n):
i = 2
while(i <= n/2+1):
if(n%i == 0):
return i
i += 1
return n
def isPrimeRange(n):
for i in range(2,n/2+1):
if(n%i == 0):
return i
return n
n = 353591872901
start = time.time()
isPrimeWhile(n)
print("%s while seconds"%(time.time() - start))
start = time.time()
isPrimeRange(n)
print("%s range seconds"%(time.time() - start))
Run the code and you will find the while loop is much faster than the range loop.I am guessing that the range(0,aLargeNumber) takes a very long time to run. 运行代码,你会发现while循环比range循环快得多。我猜测范围(0,aLargeNumber)需要很长时间才能运行。 But why in the last post mentioned above, the range method is much quicker?
但为什么在上面提到的上一篇文章中,范围方法要快得多? Any answers?
任何答案?
Since you are using Python 2+ ( your code needs to use integer division to work in Python 3+ ) you are running into the fact that Python 2+ range
generates a list of all elements and then iterates over them. 由于您使用的是Python 2+(您的代码需要使用整数除法在Python 3+中工作),因此您会遇到Python 2+
range
生成所有元素的列表然后迭代它们的事实。
This would explain the differences in time that it takes for the while
and range
functions to run. 这可以解释
while
和range
函数运行所需的时间差异。
Incedentally the code for Python 3+ needs the following change: 在Python 3+的代码中,需要进行以下更改:
def isPrimeRange(n):
for i in range(2,n//2+1): # integer division
if(n%i == 0):
return i
return n
This Python Blog Post explains in great detail the differences between range
(returns a list) and xrange
(returns an iterator) in Python 2+ and how Python 3+ has changed this functionality. 这篇Python博客文章详细解释了Python 2+中
range
(返回列表)和xrange
(返回迭代器)之间的区别以及Python 3+如何更改此功能。
A pick of the most relevent paragraph from that source is here: 从这个来源中选出最相关的段落是:
When you're using an iterator, every loop of the for statement produces the next number on the fly.
当您使用迭代器时,for语句的每个循环都会动态生成下一个数字。 Whereas the original range() function produced all numbers instantaneously, before the for loop started executing.
原始range()函数在for循环开始执行之前立即生成所有数字。 The problem with the original range() function was that it used a very large amount of memory when producing a lot of numbers.
原始range()函数的问题在于它在生成大量数字时使用了大量内存。 However it tends to be quicker with a small amount of numbers.
但是,只需少量数字就可以更快。 Note that in Python 3.x, you can still produce a list by passing the generator returned to the list() function.
请注意,在Python 3.x中,您仍然可以通过将返回的生成器传递给list()函数来生成列表。
As mentioned by others, the main issue appears to be using range
instead of range
in Python 2.7. 正如其他人所提到的,主要问题似乎是在Python 2.7中使用
range
而不是range
。 Using %timeit
, both functions are almost the same if one were to use xrange
(Python 2.7). 使用
%timeit
,如果使用xrange
(Python 2.7),这两个函数几乎相同。
%timeit isPrimeRange(n)
100000 loops, best of 3: 15.2 µs per loop
%timeit isPrimeWhile(n)
100000 loops, best of 3: 15.8 µs per loop
%load_ext line_profiler
%load_ext memory_profiler
from isPrimeRange import isPrimeRange
from isPrimeWhile import isPrimeWhile
n = 353591872901
isPrimeRange: Line Profiler isPrimeRange:Line Profiler
%lprun -f isPrimeRange isPrimeRange(n)
Timer unit: 1e-06 s
**Total time: 5.5e-05 s**
File: isPrimeRange.py
Function: isPrimeRange at line 1
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1 def isPrimeRange(n):
2 82 25 0.3 45.5 for i in xrange(2,n/2+1):
3 82 29 0.4 52.7 if(n%i == 0):
4 1 1 1.0 1.8 return i
5 return n
isPrimeWhile: Line Profiler isPrimeWhile:Line Profiler
%lprun -f isPrimeWhile isPrimeWhile(n)
Timer unit: 1e-06 s
**Total time: 9e-05 s**
File: isPrimeWhile.py
Function: isPrimeWhile at line 3
Line # Hits Time Per Hit % Time Line Contents
==============================================================
3 def isPrimeWhile(n):
4 1 1 1.0 1.1 i = 2
5 82 34 0.4 37.8 while(i <= n/2+1):
6 82 31 0.4 34.4 if(n%i == 0):
7 1 0 0.0 0.0 return i
8 81 24 0.3 26.7 i += 1
9 return n
Using iPython's memory profiler, you can see that both use the same amount of memory. 使用iPython的内存分析器,您可以看到两者都使用相同数量的内存。
isPrimeRange: Memory Profiler isPrimeRange:Memory Profiler
%mprun -f isPrimeRange isPrimeRange(n)
('',)
Filename: isPrimeRange.py
Line # Mem usage Increment Line Contents
================================================
1 24.2 MiB 0.0 MiB def isPrimeRange(n):
2 24.2 MiB 0.0 MiB for i in xrange(2,n/2+1):
3 24.2 MiB 0.0 MiB if(n%i == 0):
4 24.2 MiB 0.0 MiB return i
5 return n
isPrimeWhile: Memory Profiler isPrimeWhile:Memory Profiler
%mprun -f isPrimeWhile isPrimeWhile(n)
('',)
Filename: isPrimeWhile.py
Line # Mem usage Increment Line Contents
================================================
3 24.2 MiB 0.0 MiB def isPrimeWhile(n):
4 24.2 MiB 0.0 MiB i = 2
5 24.2 MiB 0.0 MiB while(i <= n/2+1):
6 24.2 MiB 0.0 MiB if(n%i == 0):
7 24.2 MiB 0.0 MiB return i
8 24.2 MiB 0.0 MiB i += 1
9 return n
you might as well try using 你也可以尝试使用
import time
def isPrimeWhile(n):
i = 2
while(i <= n/2+1):
if(n%i == 0):
return i
i += 1
return n
def isPrimeRange(n):
for i in xrange(2,n/2+1):
if(n%i == 0):
return i
return n
n = 353591872901
start = time.time()
isPrimeWhile(n)
print("%s while seconds"%(time.time() - start))
start = time.time()
isPrimeRange(n)
print("%s while seconds"%(time.time() - start))
1.28746032715e-05 while seconds 1.28746032715e-05秒
6.91413879395e-06 while seconds 6.91413879395e-06秒
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.