我试图找到低于1 000 000的所有素数。由于所有非素数都可以被分解为素数,我的方法是将[2,3]的素数列表开始,然后遍历每个数字最多1 000 000.如果一个数字可以被prime_list中的任何数字整除,那么它就不是素数,而是移动到下一个数字。如果这个数字不能被prime_list中的任何数字整除,那么它必须是素数,并且它会被添加到这个列表中。
为了提高效率,我添加了一个声明,只检查有问题的数字是否可以被低于此数字平方根的值整除。我认为这会减少大量的计算时间,但它实际上使我的程序需要更长的时间。任何人都可以解释原因吗?
这是我的代码:
import math
import time
start_time = time.time()
prime = [2, 3]
def prime_checker(a):
for j in prime:
if j < (int(math.sqrt(a)) +1 ): /// without this line, the program runs faster
if a % j == 0:
return False
for i in range (2, 100000):
if prime_checker(i) != False:
prime.append(i)
print prime[-1]
print "Time taken = ", time.time() - start_time
答案 0 :(得分:3)
为了进一步加快算法速度,请注意2是唯一的素数。所有其他偶数都是复合数。你已经有prime = [2, 3]
所以你可以从5开始搜索(4不是素数)并且只检查奇数:
for i in range (5, 100000, 2):
if prime_checker(i) != False:
prime.append(i)
答案 1 :(得分:2)
你反复计算a
的平方根的时间通过跳过更大的素数来压倒你所节省的任何东西。计算平方根一次,这在我的测试中比重复计算快10倍(比完全离开线快3倍)。
def prime_checker(a):
limit = int(math.sqrt(a)) + 1
for j in prime:
if j > limit:
break
if a % j == 0:
return False
return True
for i in range (2, 100000):
if prime_checker(i):
prime.append(i)
答案 2 :(得分:1)
&#34;如果此号码不能被prime_list&#34;中的任何数字整除不大于此数字的平方根,那么它就是素数。
一旦你在平方根上方击中了一个素数,其他所有人都将如此。我们事先知道 。
重点不是要检查是否要提前检查每次无关检查,而是阻止所有这些检查。这将使你的代码加速100倍,如果不是1000倍甚至更多。
换句话说,真正的问题不是sqrt
的重复计算,而是对限制条件的错误处理。通过正确处理限制条件,即使重复计算sqrt
也不重要。
并且正确的方法是:尽快从循环中断开,即当达到平方根上方的第一个素数时立即;可能直接在那里直接返回
True
。
答案 3 :(得分:0)
使用**0.5
代替math.sqrt
也会呈指数级增长:
>>> import timeit
>>> print(timeit.timeit('math.sqrt(1830374)', setup='import math', number=10000))
0.0020401941434329274
>>> print(timeit.timeit('1830374**0.5', number=10000))
0.00015091430498159752
Chepner的代码是正确的答案,但不要忘记像rossum所说的迭代。按照他说的方式迭代将为你节省50万个电话(但是,他们会使用Chepner的算法迅速破解,这仍然是浪费很多时间)。
答案 4 :(得分:0)
您的解决方案耗费O(N**1.5)
时间。要加快速度,请使用Sieve of Eratosthenes。它的时间复杂度为O(NloglogN))
。
n = 10 ** 5
sieve = [True] * n
sieve[0] = sieve[1] = False
for i in range(2, n):
if sieve[i]:
for j in range(i + i, n, i):
sieve[j] = False
primes = []
for i, j in enumerate(sieve):
if j:
primes.append(i)