Algorithm 降低埃拉托斯烯筛的空间复杂度,以在一定范围内生成素数

Algorithm 降低埃拉托斯烯筛的空间复杂度,以在一定范围内生成素数,algorithm,data-structures,primes,sieve-of-eratosthenes,space-complexity,Algorithm,Data Structures,Primes,Sieve Of Eratosthenes,Space Complexity,在通过一些测试后,我发现这是生成素数的最好、最快的方法 我想在两个数字之间生成素数,比如说a和b AFAIK,在Sieve方法中,空间复杂度是O(b) PS:我写的是Big-O而不是Theta,因为我不知道是否可以减少空间需求 我们能降低空间复杂度吗?如果空间复杂度真的是个问题,也许值得一看。从您共享的wikipedia页面获取引用 如果您有足够的空间存储sqrt(b)之前的所有素数,那么您可以使用额外的空间O(b-a)筛选a到b范围内的素数 在Python中,这可能类似于: def prime

在通过一些测试后,我发现这是生成素数的最好、最快的方法

我想在两个数字之间生成素数,比如说
a
b

AFAIK,在Sieve方法中,空间复杂度是O(b)

PS:我写的是Big-O而不是Theta,因为我不知道是否可以减少空间需求


我们能降低空间复杂度吗?

如果空间复杂度真的是个问题,也许值得一看。从您共享的wikipedia页面获取引用

如果您有足够的空间存储sqrt(b)之前的所有素数,那么您可以使用额外的空间O(b-a)筛选a到b范围内的素数

在Python中,这可能类似于:

def primesieve(ps,start,n):
  """Sieve the interval [start,start+n) for primes.

     Returns a list P of length n.  
     P[x]==1 if the number start+x is prime.  
     Relies on being given a list of primes in ps from 2 up to sqrt(start+n)."""
  P=[1]*n
  for p in ps:
    for k in range((-start)%p,n,p):
      if k+start<=p: continue
      P[k]=0
  return P
def primesieve(ps、start、n):
“”“为素数筛选间隔[start,start+n]。
返回长度为n的列表P。
如果数字start+x为素数,则P[x]==1。
依赖于给定从2到sqrt(开始+n)的ps素数列表
P=[1]*n
对于ps中的p:
对于范围内的k((-start)%p,n,p):

如果k+开始在你最喜欢的搜索引擎上搜索“埃拉托斯尼的分段筛”。如果你不想去搜索,我在我的博客上有一个。这里有两个基本的选择:通过下面的素数
sqrt(b)
(偏移量)筛选范围
[a..b]
,或奇数。没错,只要消除每个奇数的倍数,就像消除每个素数的倍数一样。在一个块中筛选范围,如果范围太宽,则在几个“段”中筛选(但如果块太窄,效率可能会降低)

在Haskell可执行伪代码中

--foldl::(r->x->r)->r->[x]->r--foldl的类型签名
primesRange_by_赔率a b=
foldl(\rx->r`neuts`[qx,qx+2*x..b])
[o,o+2..b]--列表中'r'的初始值
[3,5..floor(sqrt(from integral b))]--x的值,一个接一个
哪里
o=1+2*div a 2——范围的奇数起点
q x=x*x-2*x*min 0(div(x*x-o)(2*x))--范围内x>=x*x的第一个奇数倍
按赔率筛选将具有额外的空间复杂度O(1)(在输出/范围空间O(| b-a |)之上)

这是因为我们可以通过迭代添加2来计算赔率——不同于Eratosthenes筛下的“核心”素数,在
sqrt(b)
下面,我们必须为其保留额外的空间O(pi(sqrt(b))=~
2*sqrt(b)/log(b)
(其中
pi()
是最重要的)


剩下的问题是我们如何找到那些“核心”素数。试划分将需要额外的O(1)空间,但如果我们用埃拉托斯烯筛来做,我们需要O(sqrt(b))空间来执行核心筛本身——除非我们将其作为分段筛来执行,因此辅助空间要求为O(sqrt(sqrt(b)))。选择更适合您需要的方法。

这是某些a和b的最佳方法。对于足够大的数字,以便
b
字节或位占用太多空间,还有其他方法。尽管O(b)听起来很吓人,但它可能需要相当长的时间——一GB的内存应该可以启用
b
s多达85亿(超过32位所能列举的!)如果你对每个数字使用一个位。有没有一种方法可以让我需要一个等于a和b之间差值的空间?比如说,我们知道a和b之间的范围。我认为你只需要从2到sqrt(b)的素数,因为如果一个数字是复合的,那么至少有一个因子必须小于(或等于)sqrt。(搜索分段筛以获取更多信息)@Peterdererivaz,我认为你的方法是测试一个数字的素数,这与使用筛选算法来查找给定范围内的所有素数不同。这种方法将试除法作为一种单独的技术进行区分。因此,不清楚这对原来的问题有何帮助。@RealzSlaw。对于非常窄的范围,它是相同的,但是对于任何非消失宽度,按赔率筛选比按赔率测试快,因为我们对每一个都进行了测试,但当我们筛选时,我们跳过了越来越长的跨度(例如:
9,15,21…
121,143,165…
)并免费收集间隙中的素数。+1虽然索伦森不是埃拉托森的变体,但它是一个完全不同的筛子,具有更差的时间和更高的空间复杂度。顺便说一句,按概率筛分可能会有更差的时间cpxty,但它是O(1)个额外的空间(除了输出)。:)我也添加了一个关于它的答案。:)