如何让Python代码运行得更快?[欧拉计划问题#7]
我正在努力完成这个项目,挑战: 通过列出前六个素数:2、3、5、7、11和13,我们可以 注意第6个素数是13 第10001个素数是什么 我的代码似乎是正确的,因为它适用于小数字,例如6素数是13 我如何改进它,以便对于较大的数字(如10 001),代码将运行得更快 代码如下:如何让Python代码运行得更快?[欧拉计划问题#7],python,performance,interpreter,Python,Performance,Interpreter,我正在努力完成这个项目,挑战: 通过列出前六个素数:2、3、5、7、11和13,我们可以 注意第6个素数是13 第10001个素数是什么 我的代码似乎是正确的,因为它适用于小数字,例如6素数是13 我如何改进它,以便对于较大的数字(如10 001),代码将运行得更快 代码如下: #Checks if a number is a prime def is_prime(n): count = 0 for i in range(2, n): if n%i == 0:
#Checks if a number is a prime
def is_prime(n):
count = 0
for i in range(2, n):
if n%i == 0:
return False
break
else:
count += 1
if count == n-2:
return True
#Finds the value for the given nth term
def term(n):
x = 0
count = 0
while count != n:
x += 1
if is_prime(x) == True:
count += 1
print x
term(10001)
更新:
谢谢你的回复。我应该说得更清楚一些,我不是想加快解释器的速度,也不是想找一个更快的解释器,因为我知道我的代码不是很好,所以我一直在寻找提高代码效率的方法。没有讨论你的算法,对于这种紧凑的数值计算,解释器可以比普通的CPython解释器快得离谱。您可能想尝试一下。需要思考的几个问题:
- 你真的需要在n-1之前检查除法吗?你能多早停下来
- 除了2之外,你真的需要检查除以2的所有倍数吗
- 3的倍数是多少?5.有没有办法把这个想法推广到所有以前测试过的素数的倍数
- 速度更快的解释器无法解决问题。即使是用C或汇编语言编写的实现也不够快(在project Euler的“大约一秒钟”的时间范围内)。坦率地说,你的算法很可怜。一些研究和思考将帮助您编写一种算法,该算法在速度较慢的解释器中运行得比您当前在本机代码中实现的算法更快(我不会说出任何细节,部分原因是这是您的工作,部分原因是我无法立即判断需要多少优化).欧拉计划的目的不是真正思考学习编程,而是思考算法。对于问题10,您的算法需要比问题7等更快。因此,您需要找到一种更好的方法来查找素数,而不是更快地运行Python代码。人们在时间限制下通过思考数学来解决这些问题,而你现在使用的计算机速度要慢得多
在这一点上,如果你真的需要帮助思考这个问题,也许可以询问你的素数算法。许多Euler问题(包括这一个)的设计都是为了在几乎任何给定硬件和编译器上都能在可接受的时间内进行计算(当然,可能不是PDP-11上的INTERCAL)
你的算法可行,但它有二次复杂度。使用速度更快的解释器可以提高线性性能,但在计算10000个素数之前,二次复杂度会使其相形见绌。有些算法的复杂度要低得多;找到它们(或者用谷歌搜索,不必为此感到羞耻,你仍然会学到很多)并实现它们。基于本文中的haskell代码:
正如大多数人所说,这一切都是为了找到正确的算法。你考虑过看电影吗
要检查素数,不必运行到n-1或n/2 为了更快地运行,您只能检查n的平方根 这是我知道的最快的算法
def isprime(number):
if number<=1:
return False
if number==2:
return True
if number%2==0:
return False
for i in range(3,int(sqrt(number))+1):
if number%i==0:
return False
return True
def isprime(数字):
如果数字导入数学
计数=0
定义为素数(n):
如果n%2==0且n>2:
返回错误
对于范围(3,int(math.sqrt(n))+1,2)内的i:
如果n%i==0:
返回错误
返回真值
对于范围内的i(22000000):
如果是_素数(i):
计数+=1
如果计数=10001:
打印i
打破
导入时间
t=time.time()
定义n次素数(n):
b=[]
b、 附加(2)
而len(b)则是一个类似于蟒蛇的回答
导入时间
t=time.time()
def prime_波纹管(n):
b=[]
num=2
j=0
b、 附加(2)
而len(b)-1则以不同的方式表达。我们知道2的所有倍数都不是素数(除了2),我们也知道所有非素数都可以分解为素数成分
i、 e
12=3x4=3x2x2
30=5 x 6=5 x 3 x 2
因此,我迭代了一个奇数列表,积累了一个素数列表,并且只试图找到这个列表中有素数的奇数的模
#First I create a helper method to determine if it's a prime that
#iterates through the list of primes I already have
def is_prime(number, list):
for prime in list:
if number % prime == 0:
return False
return True
编辑:最初我是递归编写的,但我认为迭代的情况要简单得多
def find_10001st_iteratively():
number_of_primes = 0
current_number = 3
list_of_primes = [2]
while number_of_primes <= 10001:
if is_prime(current_number, list_of_primes):
list_of_primes.append(current_number)
number_of_primes += 1
current_number += 2
return current_number
def find_10001st_迭代()
素数的个数=0
当前_编号=3
素数列表=[2]
而\u素数则是一个不同的快速Python解决方案:
import math
prime_number = 4 # Because 2 and 3 are already prime numbers
k = 3 # It is the 3rd try after 2 and 3 prime numbers
milestone = 10001
while k <= milestone:
divisible = 0
for i in range(2, int(math.sqrt(prime_number)) + 1):
remainder = prime_number % i
if remainder == 0: #Check if the number is evenly divisible (not prime) by i
divisible += 1
if divisible == 0:
k += 1
prime_number += 1
print(prime_number-1)
导入数学
素数=4,因为2和3已经是素数了
k=3#这是继2和3个素数之后的第三次尝试
里程碑=10001
而k
104743
0.6159017086029053解决欧拉问题的诀窍是找到正确的算法。如果您的解决方案运行太慢,则说明您的算法错误;性能“调整”(更快地运行代码)不会有帮助。这个链接将有助于检查。一个类似的线程[我的方式:生成和枚举.+1有用的提示,尽管我怀疑我们中的许多人(包括OP)是否能够自己想出这个算法…执行前两个可能已经足够解决这个问题了。-1(不是真的)让他自己解决问题——纠正他的想法,而不是他的答案。不要发布这样的答案,让别人自己偶然发现这些要点,让他们拥有自己的灵感时刻。这会毁了它。@Dan D.-(虽然这不是问题的要求,但你可能会感兴趣),试试我的算法。(你的algo时间-0.28秒,我的algo时间-我的笔记本电脑上的0.18秒),这也更容易理解。@Guanidene我在我的笔记本电脑上对这个版本与你的进行了计时,发现你的花了0.36秒,这个版本0.19秒。这是python 2.5.2在2.2GHz上;我修改了你的ve
import time
from math import sqrt
wheel2357 = [2,4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,8,6,4,6,2,4,6,2,6,6,4,2,4,6,2,6,4,2,4,2,10,2,10]
list_prime = [2,3,5,7]
def isprime(num):
limit = sqrt(num)
for prime in list_prime:
if num % prime == 0: return 0
if prime > limit: break
return 1
def generate_primes(no_of_primes):
o = 0
n = 11
w = wheel2357
l = len(w)
while len(list_prime) < no_of_primes:
i = n
n = n + w[o]
o = (o + 1) % l
if isprime(i):
list_prime.append(i)
t0 = time.time()
generate_primes(10001)
print list_prime[-1] # 104743
t1 = time.time()
print t1-t0 # 0.18 seconds
104743
0.307313919067
def isprime(number):
if number<=1:
return False
if number==2:
return True
if number%2==0:
return False
for i in range(3,int(sqrt(number))+1):
if number%i==0:
return False
return True
import math
count = 0 <br/> def is_prime(n):
if n % 2 == 0 and n > 2:
return False
for i in range(3, int(math.sqrt(n)) + 1, 2):
if n % i == 0:
return False
return True
for i in range(2,2000000):
if is_prime(i):
count += 1
if count == 10001:
print i
break
import time
t=time.time()
def n_th_prime(n):
b=[]
b.append(2)
while len(b)<n :
for num in range(3,n*11,2):
if all(num%i!=0 for i in range(2,int((num)**0.5)+1)):
b.append(num)
print list(sorted(b))[n-1]
n_th_prime(10001)
print time.time()-t
104743
0.702000141144 second
#First I create a helper method to determine if it's a prime that
#iterates through the list of primes I already have
def is_prime(number, list):
for prime in list:
if number % prime == 0:
return False
return True
def find_10001st_iteratively():
number_of_primes = 0
current_number = 3
list_of_primes = [2]
while number_of_primes <= 10001:
if is_prime(current_number, list_of_primes):
list_of_primes.append(current_number)
number_of_primes += 1
current_number += 2
return current_number
import math
prime_number = 4 # Because 2 and 3 are already prime numbers
k = 3 # It is the 3rd try after 2 and 3 prime numbers
milestone = 10001
while k <= milestone:
divisible = 0
for i in range(2, int(math.sqrt(prime_number)) + 1):
remainder = prime_number % i
if remainder == 0: #Check if the number is evenly divisible (not prime) by i
divisible += 1
if divisible == 0:
k += 1
prime_number += 1
print(prime_number-1)
import time
t = time.time()
def is_prime(n): #check primes
prime = True
for i in range(2, int(n**0.5)+1):
if n % i == 0:
prime = False
break
return prime
def number_of_primes(n):
prime_list = []
counter = 0
num = 2
prime_list.append(2)
while counter != n:
if is_prime(num):
prime_list.append(num)
counter += 1
num += 1
return prime_list[n]
print(number_of_primes(10001))
print(time.time()-t)