我正在尝试用python进行一些计算,我的内存不足。因此,我想读/写一个文件以释放内存。我需要一个像一个非常大的列表对象的东西,所以我想为文件中的每个对象写一行,并读取/写入那些行而不是内存。行排序对我很重要,因为我将使用行号作为索引。所以我想知道如何在python中替换线条而不移动其他线条(实际上,移动线条是好的,只要它们返回到我期望它们的位置)。
我正在尝试帮助一个朋友,这个朋友在python中差于或等于我。这段代码应该找到最大的素数,它除以给定的非素数。这个代码适用于数字,直到100万这样的数字,但是在死后,我的记忆在尝试制作数字列表时会耗尽。
# a comes from a user input
primes_upper_limit = (a+1) / 2
counter = 3L
numbers = list()
while counter <= primes_upper_limit:
numbers.append(counter)
counter += 2L
counter=3
i=0
half = (primes_upper_limit + 1) / 2 - 1
root = primes_upper_limit ** 0.5
while counter < root:
if numbers[i]:
j = int((counter*counter - 3) / 2)
numbers[j] = 0
while j < half:
numbers[j] = 0
j += counter
i += 1
counter = 2*i + 3
primes = [2] + [num for num in numbers if num]
for numb in reversed(primes):
if a % numb == 0:
print numb
break
另一个编辑
如何为每个索引编写不同的文件?例如,十亿个带有长整数文件名的文件,只是文件中的一个数字?
答案 0 :(得分:2)
你想找到一个最大的素数除数。 (Project Euler Question 3) 您当前选择的算法和实现方法是:
numbers
(3&lt; = n&lt; = sqrt(a),或(a + 1)/ 2),正如您目前所做的那样)numbers
列表以获取素数列表{p}&lt; = sqrt(a)我对此算法的评论如下。正如欧文和我所评论的那样,筛分和试验分区是严重不可扩展的算法。对于大的(十亿或万亿)你真的应该使用NumPy。无论如何,有关实施此算法的一些意见:
int(math.sqrt(a))
,而不是(a + 1)/ 2吗?numbers
,然后筛选它的优势 - 数字列表不可扩展。只需直接构建列表primes
。你可以使用while / for-loops和xrange(3,sqrt(a)+2,2)
(它给你一个迭代器)。正如你在2**31L
提到xrange()溢出,但结合sqrt观察,你仍然可以成功地将因子考虑到2**62
generate_primes(a)
与find_largest_prime_divisor(a)
区分开来。分解有很大帮助。这是我对您的代码的重写,但由于保留了筛选列表,性能仍然在数十亿(a> 10 ** 11 +1)中下降。我们可以使用collections.deque代替素数列表来获得更快的O(1)append()操作,但这是一个小的优化。
# Prime Factorization by trial division
from math import ceil,sqrt
from collections import deque
# Global list of primes (strictly we should use a class variable not a global)
#primes = deque()
primes = []
def is_prime(n):
"""Test whether n is divisible by any prime known so far"""
global primes
for p in primes:
if n%p == 0:
return False # n was divisible by p
return True # either n is prime, or divisible by some p larger than our list
def generate_primes(a):
"""Generate sieved list of primes (up to sqrt(a)) as we go"""
global primes
primes_upper_limit = int(sqrt(a))
# We get huge speedup by using xrange() instead of range(), so we have to seed the list with 2
primes.append(2)
print "Generating sieved list of primes up to", primes_upper_limit, "...",
# Consider prime candidates 2,3,5,7... in increasing increments of 2
#for number in [2] + range(3,primes_upper_limit+2,2):
for number in xrange(3,primes_upper_limit+2,2):
if is_prime(number): # use global 'primes'
#print "Found new prime", number
primes.append(number) # Found a new prime larger than our list
print "done"
def find_largest_prime_factor(x, debug=False):
"""Find all prime factors of x, and return the largest."""
global primes
# First we need the list of all primes <= sqrt(x)
generate_primes(x)
to_factor = x # running value of the remaining quantity we need to factor
largest_prime_factor = None
for p in primes:
if debug: print "Testing divisibility by", p
if to_factor%p != 0:
continue
if debug: print "...yes it is"
largest_prime_factor = p
# Divide out all factors of p in x (may have multiplicity)
while to_factor%p == 0:
to_factor /= p
# Stop when all factors have been found
if to_factor==1:
break
else:
print "Tested all primes up to sqrt(a), remaining factor must be a single prime > sqrt(a) :", to_factor
print "\nLargest prime factor of x is", largest_prime_factor
return largest_prime_factor
答案 1 :(得分:0)
如果我理解正确,这不是一件容易的事。他们解释它的方式,你想保持文件句柄打开,并使用该文件作为存储字符数据的地方。
假设您有一个像
这样的文件a
b
c
你想用'bb'替换'b'。这将是一个痛苦,因为文件实际上看起来像a\nb\nc
- 你不能只覆盖b
,你需要另一个字节。
我的建议是尝试找到一种方法,使您的算法无需使用文件即可进行额外存储。如果你有一个堆栈溢出,你可能没有真正耗尽内存,你超越了调用堆栈, 更小。
您可以尝试将算法重新编写为不递归。有时您可以使用list
替换调用堆栈 - 但是您可以做很多事情,我认为我不会给出很多一般性建议而不会看到您的算法。
修改强>
啊,我明白你的意思......当列表
while counter <= primes_upper_limit:
numbers.append(counter)
counter += 2L
变得非常大,你可能会耗尽内存。所以我猜你基本上都在筛选,这就是为什么你有大名单numbers
?这说得通。如果你想继续这样做,你可以尝试一个numpy
bool
数组,因为它将每个单元使用更少的内存:
import numpy as np
numbers = np.repeat(True, a/2)
或者(也许这并不吸引人)你可以采用一种完全不同的方法,不使用大清单,例如完全分解数字并选择最大因素。
类似的东西:
factors = [ ]
tail = a
while tail > 1:
j = 2
while 1:
if tail % j == 0:
factors.append(j)
tail = tail / j
print('%s %s' % (factors, tail))
break
else:
j += 1
即说你要考虑因素20
:tail
以20
开头,然后你发现2
tail
变为10
,然后它变为5
。
对于大型(数十亿)素数而言,效率并不高,并且方式太慢,但对于具有小因子的数字,它可以。
我的意思是你的筛子也很好,直到你开始耗尽记忆力;)。你可以给numpy
一个镜头。
答案 2 :(得分:0)
pytables非常适合处理和存储大量数据。但首先要在smci的答案中实施评论,以尽量减少您需要存储的数字量。
答案 3 :(得分:0)
对于只有12位数的数字,如Project Euler#3,不需要花哨的整数分解方法,也不需要在磁盘上存储中间结果。使用此算法查找n:
的因子这只是按每个整数进行试验除法,直到达到平方根,这表明剩余的辅因子是素数。每个因素都会在找到时打印出来。