簡體   English   中英

在這種情況下,為什么while循環比范圍快得多?

[英]Why is while loop much faster than range in this case?

根據這篇文章 ,范圍循環應該比python中的while循環更快,但請看下面的代碼。 它僅用於測試數字是否為素數,如果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))

運行代碼,你會發現while循環比range循環快得多。我猜測范圍(0,aLargeNumber)需要很長時間才能運行。 但為什么在上面提到的上一篇文章中,范圍方法要快得多? 任何答案?

由於您使用的是Python 2+(您的代碼需要使用整數除法在Python 3+中工作),因此您會遇到Python 2+ range生成所有元素的列表然后迭代它們的事實。

這可以解釋whilerange函數運行所需的時間差異。

在Python 3+的代碼中,需要進行以下更改:

def isPrimeRange(n):
    for i in range(2,n//2+1): # integer division
        if(n%i == 0):
            return i
    return n 

這篇Python博客文章詳細解釋了Python 2+中range (返回列表)和xrange (返回迭代器)之間的區別以及Python 3+如何更改此功能。

從這個來源中選出最相關的段落是:

當您使用迭代器時,for語句的每個循環都會動態生成下一個數字。 原始range()函數在for循環開始執行之前立即生成所有數字。 原始range()函數的問題在於它在生成大量數字時使用了大量內存。 但是,只需少量數字就可以更快。 請注意,在Python 3.x中,您仍然可以通過將返回的生成器傳遞給list()函數來生成列表。

正如其他人所提到的,主要問題似乎是在Python 2.7中使用range而不是range 使用%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

%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

%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

使用iPython的內存分析器,您可以看到兩者都使用相同數量的內存。

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

%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

你也可以嘗試使用

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秒

6.91413879395e-06秒

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM