我对python世界和编码世界相对较新,所以我不确定如何优化我的python脚本。我的脚本如下:
import math
z = 1
x = 0
while z != 0:
x = x+1
if x == 500:
z = 0
calculated = open('Prime_Numbers.txt', 'r')
readlines = calculated.readlines()
calculated.close()
a = len(readlines)
b = readlines[(a-1)]
b = int(b) + 1
for num in range(b, (b+1000)):
prime = True
calculated = open('Prime_Numbers.txt', 'r')
for i in calculated:
i = int(i)
q = math.ceil(num/2)
if (q%i==0):
prime = False
if prime:
calculated.close()
writeto = open('Prime_Numbers.txt', 'a')
num = str(num)
writeto.write("\n" + num)
writeto.close()
print(num)
正如你们中的一些人可能猜测我正在计算素数。它调用的外部文件包含2到20之间的所有素数。 我在那里得到了while循环的原因是我希望能够控制它的运行时间。
如果您有任何关于消除任何混乱的建议,请回复并告诉我,谢谢。
答案 0 :(得分:3)
与使用整数的操作相比,读取和写入文件非常非常慢。只需删除所有文件I / O,您的算法就可以加速100倍:
import itertools
primes = {2} # A set containing only 2
for n in itertools.count(3): # Start counting from 3, by 1
for prime in primes: # For every prime less than n
if n % prime == 0: # If it divides n
break # Then n is composite
else:
primes.add(n) # Otherwise, it is prime
print(n)
更快的素数生成算法将是一个筛子。这是Eratosthenes的Sieve,在Python 3中:
end = int(input('Generate primes up to: '))
numbers = {n: True for n in range(2, end)} # Assume every number is prime, and then
for n, is_prime in numbers.items(): # (Python 3 only)
if not is_prime:
continue # For every prime number
for i in range(n ** 2, end, n): # Cross off its multiples
numbers[i] = False
print(n)
答案 1 :(得分:1)
继续存储和加载文件中的所有素数是非常低效的。通常,文件访问速度非常慢。而是将素数保存到列表或双端队列中。对于此初始化calculated = deque()
,然后只需添加calculated.append(num)
的新素数。同时输出print(num)
的素数并将结果传递给文件。
当您发现num
不是素数时,您不必继续检查所有其他除数。所以打破内循环:
if q%i == 0:
prime = False
break
您无需通过所有以前的素数来检查新的素数。由于每个非素数需要分解为两个整数,因此至少有一个因子必须小于或等于sqrt(num)
。所以限制你对这些除数的搜索。
你的代码的第一部分也让我感到恼火。
z = 1
x = 0
while z != 0:
x = x+1
if x == 500:
z = 0
这部分似乎与:
相同for x in range(500):
另外,您使用x
限制为500个素数,为什么不简单地使用计数器,如果找到素数则增加并同时检查,如果达到限制则中断?在我看来,这会更具可读性。
通常,您不需要引入限制。您只需点击Ctrl+C
即可随时中止该计划。
然而,正如其他人已经指出的那样,您选择的算法对中型或大型素数的表现非常差。有更高效的算法可以找到素数:https://en.wikipedia.org/wiki/Generating_primes,尤其是https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes。
答案 2 :(得分:0)
你正在为你的文件写一个空白行,这是一个int()追溯。另外,我猜你需要从你的新行中删除rstrip()。
我建议使用两个不同的文件 - 一个用于初始值,一个用于所有值 - 初始和最近计算。
如果您可以将值保留在内存中一段时间,那么比重复浏览文件要快得多。但是,当然,这将限制您可以计算的素数的大小,因此对于较大的值,您可以根据需要返回到文件的迭代方法。
对于计算适度大小的素数,筛子实际上相当不错,值得谷歌。
当你进入更大的素数时,前n个素数的试验划分是好的,接着是m轮的米勒 - 拉宾。如果Miller-Rabin概率性地表明这个数字可能是一个素数,那么你就完成了试验分裂或AKS或类似的。米勒拉宾可以说“这可能是一个素数”或“这绝对是复合”。 AKS给出了明确的答案,但速度较慢。
FWIW,我在http://stromberg.dnsalias.org/~dstromberg/primes/收集了一堆与素数相关的代码