【问题标题】:Handling a List of 1000000+ Elements处理包含 1000000 多个元素的列表
【发布时间】:2018-01-09 01:31:03
【问题描述】:

我正在尝试找到一种方法来找到小于 100,000,000 的素数的 prime gaps 的分布。

我的方法:

第 1 步:从 TXT 文件“primes.txt”开始,其中包含一个素数列表(最多 10,000,000 个)。

第 2 步:让程序读取文件,然后将每个数字插入到列表中,p1

第 3 步:求上界的平方根(TXT 文件中素数上限的 10 倍,在本例中为 100,000,000)并创建另一个列表 p2,其中包含所有小于或等于该平方根的素数,向上取整。

第四步:定义一个isPrime()方法,检查输入是否为素数(NB:因为我知道要检查的数字都小于100,000,000,我只有检查该数是否能被所有小于或等于 100,000,000 平方根的素数整除,即 10,000)

第 5 步:添加一个列表 l,该列表收集所有素数间隙,然后从 1 迭代到 100,000,000,检查每个数字的素数。如果这个数是素数,则记录它与它之前的最后一个素数之间的差距,并将其写入另一个文档“primes2.txt”。

第六步:输出列表l

问题:

该程序似乎需要很长时间才能运行。我觉得这个问题与我如何管理列表有关,因为它的大小(Prime Number Theorem 估计该列表中的“primes.txt”中约有 620,420 个元素)。有没有办法通过不同的处理列表来减少这个程序的运行时间?

我在下面附上了我的代码。

import math
import sys

f = open("primes.txt","r")
p1 = []
for i in f:
    p1.append(int(i))
f.close()
ml = 10000000
ms = math.sqrt(10*ml)
p2 = []
x1 = 0
while x1 < len(p1) and p1[x1] <= int(ms+0.5):
    p2.append(p1[x1])
    x1 += 1

def isPrime(n):
    for i in p2:
        if n%i == 0:
            if n/i == 1:
                return True
            return False
    return True

def main():
    l = [0]*1001 #1,2,4,6,8,10,12,...,2000 (1, and then all evens up to 2000)
    lastprime = -1
    diff = 0
    fileobject = open("primes2.txt",'w')
    for i in xrange(1,10*ml):
        if isPrime(i):
            if i > 2:
                diff = i - lastprime
                if diff == 1:
                    l[0] += 1
                else:
                    l[diff/2] += 1
            lastprime = i
            fileobject.write(str(i)+"\n")
        if i%(ml/100) == 0:
            print i/float(ml/10), "% complete"
    fileobject.close()
    print l

main()

编辑:更改了程序从文件中读取的方式

【问题讨论】:

  • 那是你的问题! ps = f.read().split('\n')
  • 嗨,是的,读取文件并放入列表并进行处理需要很长时间。改善这一点的方法很少。在这种情况下,最好使用并发性或并行性。围绕不同的线程/进程拆分工作,让它们同时执行任务。使用多处理模块并生成新进程,为其提供一大块数据,将数据放入输出队列,您可以从中获取数据。或者使用线程模块创建多个线程。
  • 1) 使用better isPrime 2) 你就像没有明天一样浪费内存。阅读有关逐行迭代文件的信息 3) 使用 Eratosthenes 筛子查找两个极端之间的所有素数。
  • 您使用素数测试代码来生成已经在主列表中的较小素数对我来说似乎很奇怪。为什么不直接使用从文件中读取的素数列表?您仍然需要生成从 1000 万到 1 亿的素数,但跳过较小的值应该会更容易一些。

标签: python list large-data


【解决方案1】:

使用eratosthenes的筛子升级prime函数。这是一个链接:

Sieve of Eratosthenes - Finding Primes Python

【讨论】:

    【解决方案2】:

    提示:

    1. 对于最初的几百万,您可以像从文件中读取它们一样快地生成素数,但您需要高效地执行此操作。见下文。 (在我最近的 MacBook Pro 上生成 n 多达 1 亿个在 Python 中大约需要 7 秒。生成多达 100,000,000 个素数需要 4 分钟。在 PyPy 中会更快,而在 C 或 Swift 中方式更快或使用带有 Numpy 的 Python)

    2. 你对记忆很粗心。示例:ps = f.read().split('\n') 然后使用该
      p1 = [int(i) for i in ps]ps 位于未使用的内存中。浪费。使用逐行读取文件的循环,以便更有效地使用内存。当您逐行阅读时,文件在转换后不会闲置在内存中。

    3. 大素数对密码学有用是有充分理由的;它们需要很长时间才能生成。 Python 不是解决这个问题的最有效的语言。

    这里有一个埃拉托色尼筛子可以试试:

    def sieve_of_e(n):
        """ Returns  a list of primes < n """
        sieve = [True] * n
        for i in xrange(3,int(n**0.5)+1,2):
            if sieve[i]:
                sieve[i*i::2*i]=[False]*((n-i*i-1)/(2*i)+1)
        return [2] + [i for i in xrange(3,n,2) if sieve[i]]
    

    【讨论】:

    • 1.虽然我知道 Eratosthenes 的筛子,因为我正在从一个已经保存了很多素数的文件(“primes.txt”)中读取,我觉得没有必要使用筛子。用筛子还快吗?
    • 2.我对程序读取文件的方式进行了更改,但现在它给了我一个错误for i in xrange(1,10*ml): OverflowError: long int too large to convert to int。 (供参考,ml = 1000000000 所以10*ml = 10000000000)。我该如何解决?
    • 3.还有哪些其他语言可以更有效地处理这个问题?很抱歉收到多个通知。
    • 用筛子还快吗?是的。
    • 如果你有旧版本的 Python,你可能需要使用 long 函数。看看int(str(2**150)) 是不是long(str(1**150)) 能治好它。您应该只使用列表理解并逐行读取文件并转换为 int 作为读取。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 2014-03-09
    • 2013-02-07
    • 2022-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多