【问题标题】:Efficient method for generating lists of large prime numbers生成大素数列表的有效方法
【发布时间】:2015-10-28 16:01:25
【问题描述】:

我想弄清楚的是,当我为较小的数字运行此代码时,它会返回列表就好了,但对于较大的数字(在我正在处理的上下文中,我会称之为小。)喜欢29996299,它会运行很长时间,我已经等了45分钟没有结果,最终不得不杀死程序。我想知道是否有更有效的方法来处理规模大于 4 或 5 位的数字。我已经测试了 range 函数的一些排列,看看是否有更好的方法来处理我想要生成的列表的限制,但似乎对计算所需的时间没有任何影响。我是 python 新手,作为程序员没有那么有经验。感谢您的宝贵时间。

在提交这篇文章之前再次运行程序,花了一个半小时左右。

该程序的功能是取用户选择的数字,用它来生成一个下界,找到边界和输入之间的所有素数并追加到列表,然后生成第二个上限并找到所有素数然后追加到list,创建一个从初始编号向前和向后扩展的列表。 该程序按我的预期运行,但没有我需要的那么快,因为我要处理的数字会很快变大,每个阶段几乎翻倍。

initial_num = input("Please enter a number. ") 

lower_1 = int(initial_num) - 1000
upper_1 = int(initial_num)
list_1 = []

for num in range(lower_1,upper_1):
   if num > 1:
       for i in range(2,num):
           if (num % i) == 0:
               break
       else:
           list_1.append(num)

lower_2 = list_1[-1]
upper_2 = list_1[-1] + 2000
list_2 = []

for num in range(lower_2,upper_2 +1):
   if num > 1:
       for i in range(2,num):
           if (num % i) == 0:
               break
       else:
           list_2.append(num)

list_3 = list_1 + list_2[1:]

print list_3

【问题讨论】:

  • 如果数字太大而您无法有效筛选从 2 到素数上限的所有数字,请使用 Miller-Rabin 测试素数 (en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test)。您尝试实施的那种试验部门效率极低。
  • 即使使用像这样的蛮力方法,您也可以通过意识到如果您在测试数字的平方根时还没有找到质因数来节省大量计算量,你永远不会。此外,除 2 和 3 外,所有素数都是 6 +/- 1 的倍数。
  • 谢谢你,John,我熟悉 Miller-Rabin 测试,但我不知道如何在 python 中实现它,我是编码新手,仍在尝试弄清楚如何使我的工作适应编程。我可以手动进行计算,但到目前为止我还没有触及到我需要收集的数据的表面。
  • 谢谢马克,关于具体方法的任何指针?作为一名业余编码员,我不知道我不知道多少,更不用说我应该寻找什么,不怕做这项工作,只是寻找一个小方向。我一直在关注的教程只让我找到了我发现的低效方法,我知道这不是最好的方法,并且处理创建类和字典来存储和调用我的研究所需的数据的方法是我还没有掌握。

标签: python performance math primes largenumber


【解决方案1】:

您可以使用更高效的算法来生成最多为 N 的整个素数列表。这就是Sieve of Erathostenes。请查看链接的文章,它甚至包含一个示例伪代码。该算法的基本思想是:

  1. 维护 L,一个潜在素数列表(最初是从 2 到 N 的所有数字)
  2. 选择下一个素数 (p) 作为 L 的第一个元素(最初为 2)
  3. 删除所有 p 的倍数,直到 N,因为它们不能是素数
  4. 从第 2 步开始重复

最后你会得到一个素数列表。

Pyhton 中的一个实现from here

def eratosthenes2(n):
    multiples = set()
    for i in range(2, n+1):
        if i not in multiples:
            yield i
            multiples.update(range(i*i, n+1, i))

print(list(eratosthenes2(100)))

为了减少内存消耗,您可以考虑使用 bitset,为每个数字存储一位。这应该可以将内存使用量减少 32 - 64 倍。可用于 python here 的 bitset 实现。

【讨论】:

  • 即使(恕我直言)对于试图找到两个给定数字之间的所有素数的人来说是正确的答案,您至少应该提供算法的一般概念,而不是提供指向维基百科页面的简单链接.
  • 这有帮助,但它会在我的计算机上遇到非常大的数字的内存错误。我应该提到我制作两个列表并将它们合并的部分原因是为了节省内存,我不需要所有素数,只需要目标数的 -1000 到 +2000 范围内的素数。你知道我可以在他们之间找到妥协的方法吗?
  • 尝试使用位集来存储数字。 N 值的上限是多少?
  • 这会有所帮助,我只是阅读了它的简要概述,唯一的问题是您提出的问题,n + 2000 适用于 29996299 因为我知道我要查找的内容在该范围内对于那个值,但是一旦我得到更大的值就不确定了。
  • 我正在查看的所有数字的范围是 -1600 和 70000000
猜你喜欢
  • 2015-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-27
相关资源
最近更新 更多