只想要一些关于我的素数发生器的反馈。例如它没关系,它是否用于很多资源等。它不使用库,它相当简单,它反映了我目前的编程技巧状态,所以不要因为我想要而退缩学习。
def prime_gen(n):
primes = [2]
a = 2
while a < n:
counter = 0
for i in primes:
if a % i == 0:
counter += 1
if counter == 0:
primes.append(a)
else:
counter = 0
a = a + 1
print primes
答案 0 :(得分:4)
有一些常见的优化:
示例:强>
def prime(x):
if x in [0, 1]:
return False
if x == 2:
return True
for n in xrange(3, int(x ** 0.5 + 1)):
if x % n == 0:
return False
return True
以上示例不会生成素数但会测试它们。您可以对代码进行相同的优化:)
我发现用Python编写的一种更有效的算法可以在下面的问题和答案中找到(使用筛子):
Simple Prime Generator in Python
我自己对筛选算法的改编:
from itertools import islice
def primes():
if hasattr(primes, "D"):
D = primes.D
else:
primes.D = D = {}
def sieve():
q = 2
while True:
if q not in D:
yield q
D[q * q] = [q]
else:
for p in D[q]:
D.setdefault(p + q, []).append(p)
del D[q]
q += 1
return sieve()
print list(islice(primes(), 0, 1000000))
在我的硬件上,我可以非常快速地生成第一百万个素数(鉴于这是用Python编写的):
prologic@daisy
Thu Apr 23 12:58:37
~/work/euler
$ time python foo.py > primes.txt
real 0m19.664s
user 0m19.453s
sys 0m0.241s
prologic@daisy
Thu Apr 23 12:59:01
~/work/euler
$ du -h primes.txt
8.9M primes.txt
答案 1 :(得分:1)
以下是在Most Elegant Way to Generate Prime Number
生成适用于C#版本的素数的标准方法def prime_gen(n):
primes = [2]
# start at 3 because 2 is already in the list
nextPrime = 3
while nextPrime < n:
isPrime = True
i = 0
# the optimization here is that you're checking from
# the number in the prime list to the square root of
# the number you're testing for primality
squareRoot = int(nextPrime ** .5)
while primes[i] <= squareRoot:
if nextPrime % primes[i] == 0:
isPrime = False
i += 1
if isPrime:
primes.append(nextPrime)
# only checking for odd numbers so add 2
nextPrime += 2
print primes
答案 2 :(得分:1)
您从这里开始:
def prime_gen(n):
primes = [2]
a = 2
while a < n:
counter = 0
for i in primes:
if a % i == 0:
counter += 1
if counter == 0:
primes.append(a)
else:
counter = 0
a = a + 1
print primes
您真的需要else分支吗?否
def prime_gen(n):
primes = [2]
a = 2
while a < n:
counter = 0
for i in primes:
if a % i == 0:
counter += 1
if counter == 0:
primes.append(a)
a = a + 1
print primes
您需要柜台吗?没有!
def prime_gen(n):
primes = [2]
a = 2
while a < n:
for i in primes:
if a % i == 0:
primes.append(a)
break
a = a + 1
print primes
您是否需要检查我是否大于sqrt(a)?不。
def prime_gen(n):
primes = [2]
a = 3
while a < n:
sqrta = sqrt(a+1)
for i in primes:
if i >= sqrta:
break
if a % i == 0:
primes.append(a)
break
a = a + 1
print primes
您真的要手动增加a吗?
def prime_gen(n):
primes = [2]
for a in range(3,n):
sqrta = sqrt(a+1)
for i in primes:
if i >= sqrta:
break
if a % i == 0:
primes.append(a)
break
这是一些基本的重构,应该会自动从您的手指中流出。
然后您测试重构的代码,查看它是否有错误并修复它:
def prime_gen(n):
primes = [2]
for a in range(3,n):
sqrta = sqrt(a+1)
isPrime = True
for i in primes:
if i >= sqrta:
break
if a % i == 0:
isPrime = False
break
if(isPrime):
primes.append(a)
return primes
最后,您摆脱了isPrime标志:
def prime_gen(n):
primes = [2]
for a in range(3,n):
sqrta = sqrt(a+1)
for i in primes:
if i >= sqrta:
primes.append(a)
break
if a % i == 0:
break
return primes
现在您完成了!
答案 3 :(得分:1)
您可以使用Python yield语句同时生成一项。儿子而不是一次获得所有物品,而是遍历生成器并一次获得一件物品。这样可以最大限度地减少资源。
这里有个例子:
from math import sqrt
from typing import Generator
def gen(num: int) -> Generator[int, None, None]:
if 2 <= num:
yield 2
yield from (
i
for i in range(3, num + 1, 2)
if all(i % x != 0 for x in range(3, int(sqrt(i) + 1)))
)
for x in gen(100):
print(x, end=", ")
输出:
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
答案 4 :(得分:1)
我对拟议的解决方案进行了改进
import math #for finding the sqare root of the candidate number
def primes(n):
test = [3] #list of primes new candidates are tested against
found = [5] #list of found primes, which are not being tested against
c = 5 #candidate number, starting at five
while c < n: #upper bound, largest candidate will be this or 1 bigger
p = True #notes the possibility of c to be prime
c += 2 #increase candidate by 2, avoiding all even numbers
for a in test: #for each item in test
if c % a == 0: #check if candidate is divisible
p = False #since divisible cannot be prime
break #since divisible no need to continue checking
if p: #true only if not divisible
if found[0] > math.sqrt(c): #is samallest in found > sqrt of c
found.append(c) #if so c is a prime, add it to the list
else: #if not, it's equal and we need to start checking for it
test.append(found.pop(0)) #move pos 0 of found to last in test
return([2] + test + found) #after reaching limit returns 2 and both lists
最大的改进是不检查偶数,仅当数字不可分割时才检查平方根,当数字变大时,后者实际上加起来。我们不需要检查平方根的原因是,测试列表仅包含小于平方根的数字。这是因为我们仅在到达第一个非素数且不能被测试中的任何数整除时才添加下一个数。该数字始终是下一个最大质数的平方,该平方也是找到的最小数。布尔值“ p”的使用对我来说有点宽容,因此可能还有改进的余地。
答案 5 :(得分:0)
我对第一个代码有一些优化,可以在参数为负数时使用:
def is_prime(x):
if x <=1:
return False
else:
for n in xrange(2, int(x ** 0.5 + 1)):
if x % n == 0:
return False
return True
print is_prime(-3)
答案 6 :(得分:0)
作为Python,通常最好返回一个生成器,它将返回无限的素数序列而不是列表。
ActiveState有一个较旧的Eratosthenes Sieve列表recipes
以下是其中一个使用itertools count更新到Python 2.7,其中包含一个步骤参数,该参数在编写原始配方时不存在:
import itertools as it
def sieve():
""" Generate an infinite sequence of prime numbers.
"""
yield 2
D = {}
for q in it.count(3, 2): # start at 3 and step by odds
p = D.pop(q, 0)
if p:
x = q + p
while x in D: x += p
D[x] = p # new composite found. Mark that
else:
yield q # q is a new prime since no composite was found
D[q*q] = 2*q
由于它是一个生成器,因此它比生成整个列表的内存效率高得多。由于它定位了复合材料,因此它也具有计算效率。
运行:
>>> g=sieve()
然后每个后续调用返回下一个素数:
>>> next(g)
2
>>> next(g)
3
# etc
然后,您可以使用islice获取边界之间的列表(即,从第一个到第X + Y个素数的第X个素数......):
>>> tgt=0
>>> tgt, list(it.islice(sieve(), tgt, tgt+10))
(0, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29])
>>> tgt=1000000
>>> tgt, list(it.islice(sieve(), tgt, tgt+10))
(1000000, [15485867, 15485917, 15485927, 15485933, 15485941, 15485959, 15485989, 15485993, 15486013, 15486041])
答案 7 :(得分:0)
获取第100个素数:
import itertools
n=100
x = (i for i in itertools.count(1) if all([i%d for d in xrange(2,i)]))
print list(itertools.islice(x,n-1,n))[0]
要素数达到100
import itertools
n=100
x = (i for i in xrange(1,n) if all([i%d for d in xrange(2,i)]))
for n in x:
print n
答案 8 :(得分:0)
您也可以通过这种方式来获取python字典中的素数
def is_prime(a):
count = 0
counts = 0
k = dict()
for i in range(2, a - 1):
k[count] = a % i
count += 1
for j in range(len(k)):
if k[j] == 0:
counts += 1
if counts == 0:
return True
else:
return False
def find_prime(f, g):
prime = dict()
count = 0
for i in range(int(f), int(g)):
if is_prime(i) is True:
prime[count] = i
count += 1
return prime
a = find_prime(20,110)
print(a)
{0: 23, 1: 29, 2: 31, 3: 37, 4: 41, 5: 43, 6: 47, 7: 53, 8: 59, 9: 61, 10: 67, 11:
71, 12: 73, 13: 79, 14: 83, 15: 89, 16: 97, 17: 101, 18: 103, 19: 107, 20: 109}