【发布时间】:2015-12-19 05:21:48
【问题描述】:
我目前正在编写一个 python 脚本来通过蛮力生成每个素数。我目前有一个 >5Mb 的文件,其中包含素数,并且当脚本运行时,它会附加它找到的任何新素数,因此文件会不断变大。每次运行脚本时,这个文件都会被读入一个列表,然后循环计算下一个数字是否是素数,任何新的素数也会被附加到这个列表中。
我的问题是,每次运行脚本时将此文件加载到内存中是否更好,或者我应该在 for 循环中读取文件的下一行,根据正在检查的数字进行处理,然后加载下一个行吗?
前者创建了一个保存在内存中的大列表,但速度非常快,第二个会更慢,因为它必须在每次循环迭代时读取文件,但我认为它不会在内存附近使用。
这是我的代码,它采用配置文件作为参数,其中包含开始查找素数的数字和读取/写入素数的文件:
import sys, math, time
def is_prime(num,primes):
square = math.floor(math.sqrt(num))
print('using all prime numbers up to %d' % square)
for p in primes:
if p <= square:
print (p, end='\r')
if (num % p) == 0:
return False
else:
return True
return True
def main(argv):
if len(sys.argv) == 2:
try:
try:
f = open(sys.argv[1], 'r+')
except IOError:
sys.exit('Error: File %s does not exist in the current directory...\nUsage: generate_primes.py <prime_file>' % sys.argv[1])
f.close()
f = open(sys.argv[1], 'r+')
low = f.readlines()
f.close()
num_to_check = int(low[0].strip('\n'))
file_name = low[1].strip('\n')
print(num_to_check)
print(file_name)
if num_to_check % 2 == 0:
num_to_check += 1
f = open(file_name, 'a+')
f.seek(0)
primes = f.readlines()
print('Processing Primes...')
for key,i in enumerate(primes):
primes[key] = int(primes[key].strip('\n'))
if primes[-1] > num_to_check:
num_to_check = primes[-1]
print('Last saved prime is bigger than config value.\nDefaulting to largest saved prime... %d' % primes[-1])
time.sleep(2)
new_primes = 0
while True:
print('Checking: %s ' % str(num_to_check), end='')
if is_prime(num_to_check,primes):
print('Prime')
f.write('%s\n' % str(num_to_check))
primes.append(num_to_check)
new_primes += 1
else:
print('Composite')
num_to_check += 2
except KeyboardInterrupt:
config_name = time.strftime('%Y%m%d-%H%M%S')
print('Keyboard Interrupt: \n creating config file %s ... ' % config_name)
c = open(config_name,'w')
c.write('%d\n%s' % (num_to_check,file_name))
c.close()
f.close()
print('Done\nPrimes Found: %d\nExiting...' % new_primes)
sys.exit()
if __name__ == '__main__':
main(sys.argv[1:])
注意:素数文件不能包含单独的 1,否则每个数字都会合成。
我只从文件中读取的一个问题是能够获取存储的最大素数的值(也就是读取文件中的最后一行)。
【问题讨论】:
-
正如你所说,这些方法有权衡。对它们进行基准测试,看看哪些更适合您的使用。 (但是,5MB 并不是很多。)
-
primes = f.readlines(); for key,i in enumerate(primes): primes[key] = int(primes[key].strip('\n'))- 我认为这不是你想要的。 -
唯一应该做的就是遍历整个列表,去掉换行符并将它们更改为整数,以便以后处理它们。