使用素数生成器进行记忆

时间:2010-12-29 17:20:45

标签: python primes

我有一个python类,它通过从第n-1个素数和增量开始生成第n个素数。然后除以列表中已经存在的所有素数(sqrt(候选))。 但是我的班级只是在某个地方陷入了无限循环,我无法弄清楚原因。

class prime_list():
    def __init__(self):
        self.primelst = [1]
        self.n = 1

    def increment(self):
        self.n+=1
        candidate = self.primelst[-1]+1
        limit = int(math.floor(math.sqrt(candidate)))
        prime = True
        while True:
            for p in self.primelst:
                if p>limit:
                    break
                if (candidate % p) == 0:
                    prime = False
                    break
            if prime:
                self.primelst.append(candidate)
                return
            else:
                candidate += 1
                limit = int(math.floor(math.sqrt(candidate)))
                prime = True

if __name__=="__main__":
    p = prime_list():
    p.increment()

5 个答案:

答案 0 :(得分:5)

问题是您将1作为起始值放在主要列表中。 increment函数会搜索不能被1整除的数字。由于没有这样的数字,它会永远搜索。

您应该从2作为初始最小素数开始,或者添加一个处理第一个素数生成的特殊情况。

答案 1 :(得分:2)

除了其他人描述的修正之外,还有一些注意事项:

  • 您不使用self.n并且不需要它,因为Python列表知道它们的长度。
  • 但是,您可以使用一些缓存来记住要检查的素数,以避免进行复杂的计算。
  • primelst作为一个标识符是丑陋的:留下像这样的随机元音是高度非Pythonic,并且在标识符名称(“list”)中包含类型名称与鸭子类型的精神背道而驰。只需用复数命名容器。
  • 首选短片功能。从添加到列表逻辑中分解出素数检测,代码变得非常简单。在嵌套循环中包含中断和返回都很难遵循。
  • 您可以将主“增量”功能作为生成器,并在生成时按需访问素数。 :)
  • 标准库中有一些工具可用于简化(a)制作无限制的计数循环和(b)检查范围内的每个除数。

因此:

class prime_list():
    def __init__(self):
        self.primes = [2]
        self.to_use = 1


    def test(self, candidate):
        # Check if we need to expand the list of used primes.
        # Written a bit paranoid-ly
        while len(self.primes) > self.to_use:
            next = self.primes[self.to_use]
            # Note the mathematical rearrangement. :)
            if candidate <= next * next: self.to_use += 1
        # Test all the primes <= sqrt(candidate).
        return all(candidate % p != 0 for p in self.primes[:self.to_use])


    def __iter__(self):
        import itertools
        for candidate in itertools.count(3):
            if self.test(candidate):
                self.primes.append(candidate)
                yield candidate


if __name__ == "__main__":
    my_primes = prime_list()
    for p in my_primes:
        print "Generated:", p
        if p > 1000000: break
    print "Number of primes generated:", len(my_primes.primes)

答案 2 :(得分:1)

这不是一个语言或算法问题,而是一个调试问题:)。 在循环中添加四个打印语句(每个条件分支一个),您将很快看到为什么您的程序似乎没有结束。 通过调查弄清楚自己发生了什么事情要好得多(教别人钓鱼而不是给他们钓鱼......)。

祝你好运!

答案 3 :(得分:1)

Karl Knechtel的回答是正确的,但是迟钝;问题是to_use进展太快太快了。

这是我的修改版本 - 我已经删除了评论。

class prime_list():
    def __init__(self):
        self.primes = [2]
        self.to_use = 0


def test(self, candidate):
    next = self.primes[self.to_use]
    if candidate >= next * next:
      self.to_use += 1
      print candidate, next
    return all(candidate % p != 0 for p in self.primes[:self.to_use])


def __iter__(self):
    import itertools
    for candidate in itertools.count(3,2):
        if self.test(candidate):
            self.primes.append(candidate)
            yield candidate


if __name__ == "__main__":
    my_primes = prime_list()
#    print my_primes.primes[0]
    for p in my_primes:
        print "Generated:", p
        if p > 1000000: break
        sum += p
    print "Number of primes generated:", len(my_primes.primes)

答案 4 :(得分:0)

让我们一起跑:

// self.primelst = [1]
// self.n = 1

def increment(self):
        self.n+=1 // self.n = 2
        candidate = self.primelst[-1]+1 //candidate = 2
        limit = int(math.floor(math.sqrt(candidate))) // limit = 1
        prime = True // prime = True
        while True:
            for p in self.primelst: // p = 1
                if p>limit: // False
                    break // Does not go here
                if (candidate % p) == 0: // 2 % 1 == 0: True
                    prime = False // prime = False
                    break // breaks
            if prime: // False
                self.primelst.append(candidate) // Does not go here
                return // Does not return
            else: // Goes here
                candidate += 1 // candidate = 3
                limit = int(math.floor(math.sqrt(candidate))) // limit = 1
                prime = True // prime = True

所以while循环无休止地重复。算法错了。