【问题标题】:How to find a given number of prime numbers?如何找到给定数量的素数?
【发布时间】:2012-02-21 19:18:05
【问题描述】:

我需要从2开始按升序找到一定数量的素数。我有一个工作算法,它将数量限制作为参数 - 它找到所有小于限制的素数。

例如 - 对于参数 20,它将返回 2,3,5,7,11,13,17,19,但我需要输入 5 并获取 2,3,5,7,11。什么是最好的方法?我正在使用 Eratosthenes 的筛子,没有办法限制数字删除部分,因为我不知道第 195 个素数有多大,因此我不知道是否应该删除所有 2 的倍数1568或1268426。希望问题清楚,谢谢帮助

【问题讨论】:

  • 你能提供你的代码或至少一些伪代码吗?
  • 另见:projecteuler.net/problem=7 - 如果你解决了它,你将获得一些有用的资源。
  • @KorhanÖztürk 不,这是一个较早的编程竞赛的一部分,特别是在算法方面,这让我很烦
  • 我明白了。那么,下面的算法对你有用吗? @Magicmaster

标签: algorithm primes


【解决方案1】:

您可以在最初的埃拉托色尼筛法背后采用相同的想法,但要反复进行。

find_n_primes(num_primes):
  primes = [2]
  i = 3
  while primes.size < num_primes:
    is_prime = true
    for p in primes:
      if p > sqrt(i):
         break
      if i % p == 0: 
        is_prime = false
        break
    if is_prime:
      primes.add(i)

    i++
  return primes

基本上,与其将每个数字的倍数取到一个固定点,不如遍历 n,然后检查您已经找到的所有素数。

【讨论】:

  • 这似乎是对的,但假设我有一个要删除非素数的数字数组,我不知道数组应该有多大以及我应该删除多大的数字
  • [评论解释我的反对意见。]这可行,但会很慢;它是 num_primes'th 素数大小的二次方。如果你试图找到第百万个素数,你会看到这一点。而且算法是试除法,而不是埃拉托色尼筛法。请参阅我的答案以获得更好的解决方案。
  • @Magicmaster 你不知道。你建立一个向量/列表/任何你去的素数。您不是从列表中删除,而是添加到向量中。
  • @user448810 这并不意味着它无效(我的描述除外)。根据他的描述,听起来他不是在追求百万素数,因此可能不需要超级优化的东西。此外,您正在执行每个数字的最大 sqrt(n) 分割,因此您
  • 我明白了。我认为这与筛子没有太大关系,因为它的重点是要有一个数字数组并删除每个素数的倍数,而不是检查一个数字是否是素数。但这应该足够了,因为我只需要数千个素数
【解决方案2】:

有几种方法可以做你想做的事。

素数定理说小于n的素数个数渐近等于n/log(n)。您可以添加一个小缓冲区,然后进行 Eratosthenes 筛,并丢弃任何超出限制的素数。

而不是近似值,有一些公式可以计算小于 n 的素数的确切数量,而不列出素数。您可以使用其中一个公式找到第 n 个素数,然后使用筛子制作素数列表。如果您想采用这种方法,请在 Google 上搜索“Legendre 总和”和“Lehmer 公式”。

您可以使用分段的埃拉托色尼筛。筛到一些方便的限度。如果你有答案,请停下来。否则,选择下一个片段,然后选择下一个片段,依此类推,直到找到所需的素数。

有一种非常聪明的方法可以生成无限的素数列表,它用优先级队列替换埃拉托色尼筛的位数组。谷歌搜索 Melissa O'Neill 的论文 The Genuine Sieve of Eratosthenes

你可以看到所有这些算法的完整解释和实现here

顺便说一下,第 195 个素数是 1187。有 247 个小于 1568 的素数,还有 97790 个小于 1268426 的素数。

【讨论】:

  • 在我看来,最好的选择是分段筛和整体筛,其上限源自素数定理加上一个小缓冲区。优先队列方法很慢。
  • 同意。素数不超过n的上界其实有一个精确的公式,你可以在任何数论教科书中查到。但它与标记相差甚远,使用 n / log(n) 近似值可能会更好。 PS to Fischer:感谢您的编辑。
【解决方案3】:

前段时间,我写了一个处理素数的小模块(它满足了我在处理 Project Euler 的东西时的需要)。这是相当快的,因为它会跟踪它所看到的素数列表。这大大减少了计算时间。

这是您需要的主要例程(用 python 编写)。文档很一般,但我希望这会有所帮助。

def primes(num, l=[]):

    # l is the list of prime numbers you already have
    # This is reused to check for primality of a number

    if len(l) == 0: l = get_list() # Read from disk

    # Check to see if a sublist can be created
    e = l[-1]
    if (num < e):
        res = search.binary_low(l, num)
        return l[:res[0]+1]

    e = 6*(ceil(e/6))

    lim = num + 1
    # Extend the current list
    for n in range(e, lim, 6):
        m = n - 1
        if isprime(m, l): l.append(m)
        m = n + 1
        if isprime(m, l): l.append(m)

    # Save to pickle
    set_list(l) # Write to disk

    return l

你可以在这里找到相关的例程

https://github.com/pavanky/expo/blob/master/python/prime.py

https://github.com/pavanky/expo/blob/master/python/search.py

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-16
    • 2021-05-12
    • 1970-01-01
    • 2017-05-03
    • 2012-05-04
    • 1970-01-01
    • 2021-01-31
    • 1970-01-01
    相关资源
    最近更新 更多