Java 素数生成的动态筛选算法

Java 素数生成的动态筛选算法,java,c++,algorithm,primes,sieve,Java,C++,Algorithm,Primes,Sieve,我正在实施埃拉托什尼筛,对此的解释请参见。然而,我想调整它来生成M个素数,而不是素数1到N。我这样做的方法只是创建一个足够大的N,这样所有M个素数都包含在这个范围内。有人有什么好的启发法来模拟素数的增长吗?如果你想发布代码片段,我在java和C++中实现这个。< p>生成m素数,你需要到m m log m。参见素数定理。为了安全起见,您可能需要高估——比如N=M(logm+1) 编辑后添加:正如大卫·哈曼指出的那样,这种高估并不总是足够好的。维基百科的文章给出了M(logm+logm)作为M>=

我正在实施埃拉托什尼筛,对此的解释请参见。然而,我想调整它来生成M个素数,而不是素数1到N。我这样做的方法只是创建一个足够大的N,这样所有M个素数都包含在这个范围内。有人有什么好的启发法来模拟素数的增长吗?如果你想发布代码片段,我在java和C++中实现这个。

< p>生成m素数,你需要到m m log m。参见素数定理。为了安全起见,您可能需要高估——比如N=M(logm+1)


编辑后添加:正如大卫·哈曼指出的那样,这种高估并不总是足够好的。维基百科的文章给出了M(logm+logm)作为M>=6的安全上限。

为什么不动态增加筛子?每当需要更多素数时,重新分配seive内存,并使用以前找到的素数在新空间上运行sieve算法。


n次素数的近似值取自维基百科;因此,您只需要分配一个数组
m*log(m)+m*log(log(m))
;一个
m*log(m)
数组将是不够的。

我想到了惰性计算(例如Haskell和其他函数式语言为您提供)。虽然你用命令式语言写作,但我认为你可以运用这个概念


考虑从候选集中删除剩余基数的操作。在不涉及实际算法的情况下(更重要的是,不要猜测您将创建多少个数字),当您尝试获取剩余的最小数字时,以惰性方式执行此操作(您必须以命令式语言实现此操作)。

另一种选择是分段筛选。把数字筛到一百万。然后是第二个百万。然后是第三个。等等等你够了再停下来


为下一段重新设置筛网并不困难。有关详细信息,请参见my。

Re“为了安全起见,您可能需要高估--比如说N=M(log M+1)”--这还不够保守。示例:1619素数是13693,但您的表达式只能得到13582.7。维基文章确实给出了一个适用于所有M>5的有效上限,N=M log(M log M)@David:谢谢你指出这一点!我已经编辑了我的答案。但是我在链接文章中没有看到你的表达式M log(M log M)。M log(M log M)=M log M+M log M。这直接来自于log(AB)=log A+log B以及乘法对加法的分布。我不知道为什么wiki文章使用了更详细的标识右侧。如果你不相信我的数学,请相信Wolfram Alpha:。向下滚动到“假设M为正的替代形式:”。@David:我上次没有回复你的评论的唯一原因是我太尴尬了。当然,您的逻辑是无可挑剔的。您可以使用两个数组实现筛选算法的一个版本,两个数组的大小都等于您希望查找的素数。一个持有素数,另一个持有同一索引上素数的素数倍数。这样你就不需要计算筛子的大小(你的问题中的N)。再加上这会破坏筛子的点,每次我增加筛子时,我都必须重复之前发现的每一个素数,这大大减慢了我的程序。对,我想这就是已知的分段筛子。只需澄清一点,您当然不会从一开始就重新开始,而是用每个新的素数筛选连续素数平方之间不断增加的跨度(因此无需“**重新分配”)。当内存不足时,您开始使用较短的筛选数组@jozefg,只有这样性能才会开始受到影响。