为什么这种寻找素数的筛选方法比蛮力慢
Why this sieve method of finding primes is slower than a brute force
新手 python 尝试在这里使用 Prime Finding 程序学习!
我知道这是一个常见问题,根据我的研究,我知道我可以进行一些优化:
1) 预先分配一个固定的布尔值数组,因此不需要调整大小
2) 使用原语而不是对象
然而,我还是不明白为什么这个筛子这么慢,有什么想法吗?两者都使用附加到列表并迭代它们。我的直觉是筛子只需要检查 less 个数字。
输出
Without Sieve
0:00:00.008019
With Sieve
0:00:00.075880
prime.py用作主class
def timeMethod(methodToTime, methodVar, methodVar2):
#
start = datetime.now()
if methodVar2 == None and methodVar == None:
methodToTime()
elif methodVar2 == None:
methodToTime(methodVar)
else:
methodToTime(methodVar, methodVar2)
end = datetime.now()
time_elapsed = end - start
return time_elapsed
if __name__ == "__main__":
import sys, SingleThreadPrimes
print("Without Sieve")
print(str(timeMethod(SingleThreadPrimes.getXPrimes, 1000, None)))
print("With Sieve")
print(str(timeMethod(SingleThreadPrimes.getXPrimesSieve, 1000, None)))
#testSuite(SingleThreadPrimes.getXPrimesSieve, None, None)
SingleThreadedPrimes.py
import math
def getXPrimes(num):
primeList = []
primeList.append(2)
candidate = 3
while len(primeList) < num:
isPrime = True
for x in range(2, int(math.sqrt(candidate) + 1), 2):
if candidate % x == 0:
isPrime = False
break
if isPrime:
primeList.append(candidate)
candidate += 2
return primeList
def getXPrimesSieve(num, primeList = None):
if primeList == None:
primeList = []
if len(primeList) == 0:
primeList.append(2)
primeList.append(3)
elif len(primeList) == 1:
primeList.append(3)
if num > len(primeList):
candidate = int(primeList[len(primeList) - 1]) + 2
while len(primeList) < num:
isPrime = True
for x in primeList:
x = int(x)
if candidate % x == 0:
isPrime = False
break
elif x > int(math.sqrt(candidate)):
break
if isPrime:
primeList.append(candidate)
candidate += 2
return primeList
除其他事项外,getXPrimes
实际上并不是在寻找质数(您只测试 2
的倍数的可除性,奇数永远不会失败),而 getXPrimesSieve
是,所以你是在比较苹果和橘子。
除此之外,getXPrimesSieve
对提高性能没有太大作用,而且还在做一些损害性能的事情;它仍然必须执行许多剩余操作(一个好的筛子不会);虽然它试图避免测试高于被测试数字平方根的数字,但它通过重新计算 每个 素数的平方根来测试,这比一次计算要昂贵得多在前面,如 getXPrimes
.
要点是,您需要使您的代码既能工作又能比天真的试验除法更好。我建议查看有用的筛选算法,例如为了找到达到某个界限的所有素数,the Sieve of Eratosthenes 分摊了 "virtual" 试验除法的成本,而根本没有实际进行除法或余数工作,这 运行 比你的任何一个都快得多尝试。
新手 python 尝试在这里使用 Prime Finding 程序学习!
我知道这是一个常见问题,根据我的研究,我知道我可以进行一些优化: 1) 预先分配一个固定的布尔值数组,因此不需要调整大小 2) 使用原语而不是对象
然而,我还是不明白为什么这个筛子这么慢,有什么想法吗?两者都使用附加到列表并迭代它们。我的直觉是筛子只需要检查 less 个数字。
输出
Without Sieve
0:00:00.008019
With Sieve
0:00:00.075880
prime.py用作主class
def timeMethod(methodToTime, methodVar, methodVar2):
#
start = datetime.now()
if methodVar2 == None and methodVar == None:
methodToTime()
elif methodVar2 == None:
methodToTime(methodVar)
else:
methodToTime(methodVar, methodVar2)
end = datetime.now()
time_elapsed = end - start
return time_elapsed
if __name__ == "__main__":
import sys, SingleThreadPrimes
print("Without Sieve")
print(str(timeMethod(SingleThreadPrimes.getXPrimes, 1000, None)))
print("With Sieve")
print(str(timeMethod(SingleThreadPrimes.getXPrimesSieve, 1000, None)))
#testSuite(SingleThreadPrimes.getXPrimesSieve, None, None)
SingleThreadedPrimes.py
import math
def getXPrimes(num):
primeList = []
primeList.append(2)
candidate = 3
while len(primeList) < num:
isPrime = True
for x in range(2, int(math.sqrt(candidate) + 1), 2):
if candidate % x == 0:
isPrime = False
break
if isPrime:
primeList.append(candidate)
candidate += 2
return primeList
def getXPrimesSieve(num, primeList = None):
if primeList == None:
primeList = []
if len(primeList) == 0:
primeList.append(2)
primeList.append(3)
elif len(primeList) == 1:
primeList.append(3)
if num > len(primeList):
candidate = int(primeList[len(primeList) - 1]) + 2
while len(primeList) < num:
isPrime = True
for x in primeList:
x = int(x)
if candidate % x == 0:
isPrime = False
break
elif x > int(math.sqrt(candidate)):
break
if isPrime:
primeList.append(candidate)
candidate += 2
return primeList
除其他事项外,getXPrimes
实际上并不是在寻找质数(您只测试 2
的倍数的可除性,奇数永远不会失败),而 getXPrimesSieve
是,所以你是在比较苹果和橘子。
除此之外,getXPrimesSieve
对提高性能没有太大作用,而且还在做一些损害性能的事情;它仍然必须执行许多剩余操作(一个好的筛子不会);虽然它试图避免测试高于被测试数字平方根的数字,但它通过重新计算 每个 素数的平方根来测试,这比一次计算要昂贵得多在前面,如 getXPrimes
.
要点是,您需要使您的代码既能工作又能比天真的试验除法更好。我建议查看有用的筛选算法,例如为了找到达到某个界限的所有素数,the Sieve of Eratosthenes 分摊了 "virtual" 试验除法的成本,而根本没有实际进行除法或余数工作,这 运行 比你的任何一个都快得多尝试。