Python中的基本素数生成器

时间:2015-04-23 02:36:06

标签: python

只想要一些关于我的素数发生器的反馈。例如它没关系,它是否用于很多资源等。它不使用库,它相当简单,它反映了我目前的编程技巧状态,所以不要因为我想要而退缩学习。

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

9 个答案:

答案 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
  • 覆盖基本案例
  • 仅迭代到n
  • 的平方根

以上示例不会生成素数但会测试它们。您可以对代码进行相同的优化:)

我发现用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}