简体   繁体   English

在这种情况下,为什么while循环比范围快得多?

[英]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. 这可以解释whilerange函数运行所需的时间差异。

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.

相关问题 为什么在 Python 中循环 range() 比使用 while 循环更快? - Why is looping over range() in Python faster than using a while loop? 为什么这个问题的 for 循环解决方案比我的 while 循环解决方案快得多? 我完全被难住了 - Why is this for loop solution to this problem sooooo much faster than my while loop solution? I'm completely stumped 在这种情况下,为什么 awk 比 python 快这么多? - Why is awk so much faster than python in this case? 为什么嵌套循环比扁平循环执行得快得多? - Why does a nested loop perform much faster than the flattened one? 为什么 Python any( pred for _ in _ ) 比 for 循环快得多 - Why is Python any( pred for _ in _ ) much faster than for loop 为什么while循环比for循环更有效? - Why is a while loop much more efficient than a for loop here? 性能-为什么具有范围的素数生成算法比使用素数列表要快得多? - Performance - why is a prime-generating algorithm with range much faster than using prime list? 为什么any()比in这么快? - Why is any() so much faster than in? 为什么“in”生成器比python中的“in”列表快得多 - why "in" generator is much faster than "in" list in python 为什么切片比“手动”分配快得多? - Why is slicing much faster than "manual" assignment?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM