找到所有先前的下一个素数

 不会游泳的小饼儿 发布于 2023-02-09 14:40

我正在写一个递归无限素数生成器,我几乎可以肯定我可以更好地优化它.

现在,除了前十几个素数的查找表之外,每次调用递归函数都会收到所有先前素数的列表.

因为它是一个懒惰的生成器,所以现在我只是过滤掉任何以前的素数为0的任何数字,并取出第一个未经过滤的结果.(检查我正在使用短路,因此,当前一个素数首次将当前数字均分时,它会中止该信息.)

现在,我在搜索第400个素数(37,813)时性能下降.我正在寻找方法来使用我有一个所有先前质数列表的独特事实,并且我只搜索下一个,以改进我的过滤算法.(我能找到的大多数信息提供非懒筛找到下一个素数的限制,或方法来查找与p ñ个素数给定P N-1 ,不优化,求P ñ给出2.P N-1的素数. )

例如,我知道在p Ñ个素数必须驻留在范围(P N-1 + 1)...(P n-1个 + P N-2 ).现在我开始在p n-1 + 2 处对整数进行滤波(因为p n-1 + 1只能是p n-1 = 2的素数,这是预先计算的).但由于这是一个懒惰的生成器,知道范围的终端边界(p n-1 + p n-2)并没有帮助我过滤任何东西.

鉴于所有以前的素数,我能做些什么来更有效地过滤?

代码示例

  @doc """
  Creates an infinite stream of prime numbers.

    iex> Enum.take(primes, 5)
    [2, 3, 5, 7, 11]

    iex> Enum.take_while(primes, fn(n) -> n < 25 end)
    [2, 3, 5, 7, 11, 13, 17, 19, 23]

  """
  @spec primes :: Stream.t
  def primes do
    Stream.unfold( [], fn primes ->
      next = next_prime(primes)
      { next, [next | primes] }
    end )
  end

  defp next_prime([]),      do: 2
  defp next_prime([2 | _]), do: 3
  defp next_prime([3 | _]), do: 5
  defp next_prime([5 | _]), do: 7
  # ... etc

  defp next_prime(primes) do
    start = Enum.first(primes) + 2
    Enum.first(
      Stream.drop_while(
        Integer.stream(from: start, step: 2),
        fn number ->
          Enum.any?(primes, fn prime ->
            rem(number, prime) == 0
          end )
        end
      )
    )
  end

primes函数以空数组开始,获取它的下一个素数(2最初),然后1)从Stream发出它并且2)将它添加到下一个调用中使用的素数堆栈的顶部.(我确定这个堆栈是一些减速的来源.)

next_primes函数接收该堆栈.从最后一个已知的素数+ 2开始,它创建一个无限的整数流,并删除每个整数,该整数按列表的任何已知素数均匀划分,然后返回第一个匹配项.

我想这是类似于懒惰增量的Eratosthenes的筛子.

你可以看到一些基本的优化尝试:我开始检查p n-1 +2,然后我跳过偶数.

我只是通过每次计算传递Integer.stream来尝试更加逐字的Eratosthenes的筛子,并在找到一个素数之后,将Integer.stream包装在一个新的Stream.drop_while中,只过滤掉那些素数的多个.但是由于Streams是作为匿名函数实现的,因此会破坏调用堆栈.

值得注意的是,我并不认为您需要所有先前的素数来生成下一个素数.由于我的实施,我碰巧有它们.

2 个回答
  • 当使用Eratosthenes算法的筛子从素数生成复合材料时,您不需要所有先前的素数,只需要那些低于当前生产点的平方根的素数就足够了.

    这大大降低了内存需求.那么素数就是那些不在复合体中的奇数.

    每个素数p从其正方形开始产生其倍数的链,以2p的步长枚举(因为我们仅使用奇数).这些具有其步长值的倍数存储在字典中,从而形成优先级队列.在该优先级队列中仅存在直到当前候选的平方根的素数(与E的分段筛的存储器要求相同).

    象征性地,SoE是

         P = {3,5,7,9,...}\U {{ p 2,p 2 + 2p,p 2 + 4p,p 2 + 6p, ...} | p in P }

    每个(奇数)素数生成其倍数的流; 当所有这些流合并在一起时,我们拥有所有(奇数)复合数; 没有复合材料(和2),素数都是可能的.

    在Python中(希望可以读作可执行的伪代码),

    def postponed_sieve():                   # postponed sieve, by Will Ness      
        yield 2; yield 3; yield 5; yield 7;  # original code David Eppstein, 
        D = {}                               #            ActiveState Recipe 2002
        ps = (p for p in postponed_sieve())  # a separate Primes Supply:
        p = ps.next() and ps.next()          # (3) a Prime to add to dict
        q = p*p                              # (9) when its sQuare is 
        c = 9                                # the next Candidate
        while True:
            if c not in D:                # not a multiple of any prime seen so far:
                if c < q: yield c         #   a prime, or
                else:   # (c==q):         #   the next prime's square:
                    add(D,c + 2*p,2*p)    #     (9+6,6 : 15,21,27,33,...)
                    p=ps.next()           #     (5)
                    q=p*p                 #     (25)
            else:                         # 'c' is a composite:
                s = D.pop(c)              #   step of increment
                add(D,c + s,s)            #   next multiple, same step
            c += 2                        # next odd candidate
    
    def add(D,x,s):                          # make no multiple keys in Dict
        while x in D: x += s                 # increment by the given step
        D[x] = s  
    

    一旦产生素数,它就会被遗忘.一个单独的主要供应来自同一个生成器的单独调用,递归地,以维护字典.而那个的主要供应也是从另一个中提取的,也是递归的.每个都需要仅提供到其生产点的平方根,因此总体上需要很少的生成器,并且它们的大小渐近无关紧要(sqrt( sqrt( N))等等).

    2023-02-09 14:42 回答
  • 对于任何数字k,您只需要尝试除了包括√k在内的素数.这是因为大于任何素√k需要与原相乘√k.

    证明:

    √k*√k= k so (a +√k)*√k> k(对于所有0 <a <(k-√k)).由此得出,如果存在小于√k的另一个除数,则(a +√k)k.

    这通常用于加速寻找素数.

    2023-02-09 14:43 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有