Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当在Python中作为函数调用时,Erostenes的筛选速度要慢得多_Python_Python 3.x_Math_Primes_Sieve - Fatal编程技术网

当在Python中作为函数调用时,Erostenes的筛选速度要慢得多

当在Python中作为函数调用时,Erostenes的筛选速度要慢得多,python,python-3.x,math,primes,sieve,Python,Python 3.x,Math,Primes,Sieve,我有两段代码,我写这两段代码都是为了应用埃拉托斯烯筛,将所有素数相加到2000000。第一个块是未包装在任何函数中的原始代码,如下所示: N = 2000000 is_prime = (N + 1) * [True] for candidate in range(2, N + 1): if is_prime[candidate]: print(candidate) for witness in range(2 * candidate, N + 1, ca

我有两段代码,我写这两段代码都是为了应用埃拉托斯烯筛,将所有素数相加到2000000。第一个块是未包装在任何函数中的原始代码,如下所示:

N = 2000000
is_prime = (N + 1) * [True]

for candidate in range(2, N + 1):
    if is_prime[candidate]:
        print(candidate)
        for witness in range(2 * candidate, N + 1, candidate):
            is_prime[witness] = False
第二段代码将此功能拆分为一个检查素性的函数,然后是一个指定上界的for循环。详情如下:

  def is_prime(n):
  is_prime = (n + 1) * [True]

  for candidate in range(2, int(sqrt(n)) + 1):
      if is_prime[candidate]:
          for witness in range(2 * candidate, n+1, candidate):
              is_prime[witness] = False

  return is_prime[n]

for candidate in range(2, LIMIT):
    if is_prime(candidate):
        print(candidate)

然而,分割成检查素性的函数的代码块的速度是无限慢的。我一辈子都搞不清楚这些代码块之间的区别是什么。我做错了什么?

您的第二个实现将列表
保留为本地。在每次函数调用时,它通过将列表初始化为
(n+1)*[True]
来“重新启动”计算

因此,通过重新启动工作,在使用第二个实现时,基本上可以完成N倍的工作

编辑:正如@Aaron在评论中正确指出的,您对print()的调用也会使第二个版本变慢

问题

概括起来,存在以下问题:

  • 使用函数的实现将重新启动其工作
  • 第二个实现执行打印。第一个没有,显然更快
  • 作为旁注:您的
    is_prime
    列表与您的函数具有相同的名称。例如,当使用递归时,这将导致麻烦
改进


作为一个非常简单的改进,您可以尝试(重命名并)将
is_prime
列表移动到全局变量中。然后,当使用尚未在列表中的数字调用is_prime(n)时,您可以扩展列表(例如,
some_list+=difference*[True]
)并仅计算差值

在此基础上,您可以提到MemorizationEdit:对不起,误解了您关于打印的评论。是的,印刷也有影响。但我想说,考虑到重启所做的额外工作,这是可以忽略不计的。@Aaron,谢谢。用你的评论扩展了我的答案。Flurin,非常感谢你的及时和深入的回复!正如我所说,这是我关于stackoverflow的第一篇文章,如此迅速地得到如此有用的回复是非常令人鼓舞的。然而,正如你所建议的,我在循环外移动了+prime,但它似乎没有对速度产生影响。我还发现,一旦找到最大的素数,非功能代码块似乎将停止尝试访问is_素数列表,而第二个代码块将继续访问它提供的每个证人的列表。我通过打印每个证人的身份证明了这一点。伊森,不客气!不幸的是,这比移动列表要复杂得多。假设您调用的是_素数(4)。然后,您的列表将包含数字2、3、4和5的[…(省略0和1)…真、真、假、真]。如果调用is_prime(10),则需要执行以下步骤:首先,将数字6的列表扩大到10(现在的大小为11)。第二,对于数字6到10,试着用你找到的每一个素数(列表中带True的素数)除以它们。