【问题标题】:Prime Generation using Sieve of Eratosthenes with better performance使用具有更好性能的埃拉托色尼筛法的素数生成
【发布时间】:2015-05-23 09:57:03
【问题描述】:

要生成最多 N i 的 Prime 是使用此代码。

private static void primePrint(int n) {
        int sum=0;
        int maxFactor= (int)Math.sqrt(n);
        boolean[] isPrime=new boolean[n + 1];
        int len=isPrime.length;
        Arrays.fill(isPrime,true);
        isPrime[0]=false;
        isPrime[1]=false;
        for(int i=0;i<=maxFactor;i++){
            if(isPrime[i]){
                for(int j=i+i;j<len;j+=i){
                    isPrime[j]=false;
                }
            }
        }
        for(int i=2;i<=n;i++){
            if(isPrime[i]){
                System.out.println(i)
            }
        }

    }

但最近有人建议我将 maxfactor 减半并使用此循环,因为它可以提高效率。但我无法了解它是如何运作的。

maxFactor = maxFactor/2 - 1;
    boolean[] isPrime = new boolean[n/2+1];
    for(int i = 0; i < maxFactor; ++i) {
        if (!isPrime[i]) {

            for(int j = 2*i*(i+3)+3, p = 2*i+3; j < n/2; j += p) {
                isPrime[j] = true;
            } 

如果有人能对此有所了解,那将有很大帮助。

编辑:使用此生成 nthPrime 的工作代码

class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        System.out.println(nthPrime(25));
    }

    public static int nthPrime(int n) {
    if (n < 2) return 2;
    if (n == 2) return 3;
    int limit, root, count = 1;
    limit = (int)(n*(Math.log(n) + Math.log(Math.log(n)))) + 3;
    root = (int)Math.sqrt(limit) + 1;
    limit = (limit-1)/2;
    root = root/2 - 1;
    boolean[] sieve = new boolean[limit];
    for(int i = 0; i < root; ++i) {
        if (!sieve[i]) {
            ++count;
            for(int j = 2*i*(i+3)+3, p = 2*i+3; j < limit; j += p) {
                sieve[j] = true;
            }
        }
    }
    int p;
    for(p = root; count < n; ++p) {
        if (!sieve[p]) {
            ++count;
        }
    }
    return 2*p+1;
}
}

IDEONE LINK

【问题讨论】:

  • 您在寻找特定类型的素数吗?
  • 我无法通过减少检查的次数甚至是根的一半然后检查直到 n/2 才知道如何生成直到 n 的所有素数。以及j = 2*i*(i+3)+3, p = 2*i+3 实际在做什么。
  • 这是埃拉托色尼筛的标准优化;它只筛选奇数,因为除 2 之外的所有偶数都是合数。请参阅 my blog 上对 j 公式的解释和推导。

标签: java performance primes


【解决方案1】:

但最近有人建议我将 maxfactor 减半并使用此循环,因为它可以提高效率。

我怀疑那个“某人”是错的。 (也许他们在取笑你……)

maxFactor == sqrt(N) 背后的原因是:

  • 筛子是删除不是素数的数字
  • 如果 X 不是素数,则它必须至少有两个素数因子。
  • 如果 X 小于 N,则其质因数中至少有一个必须小于或等于 sqrt(N)

但是,如果您使 maxFactor 小于 sqrt(N),那么您可能不会删除一个或多个非素数。换句话说,你在筛子上打了一个洞。


您修改后的版本中的内部循环对我来说毫无意义......作为埃拉托色尼筛法的实现。


事实上,根据您提供的链接上的代码,我认为这是Sieve of Sundaram(不是您标记的埃拉托色尼筛子。)我还注意到该链接上的代码正在解决另一个问题:找到第 N 个素数(并非所有素数都小于或等于 N)。

无论如何,我的回答是对您关于实施埃拉托色尼筛法的问题的回答。

(如果你想要解决 Sundaram 筛的问题……你已经有了。)

【讨论】:

  • 好吧,如果你看看他的代码,他正在解决一个不同的问题。他正在寻找第 N 个素数,而不是所有小于 N 的素数。
  • 但他正在计算所需的 seive,然后将哪些不是素数标记为真?所以我们不能扩展它来生成素数直到 N 吗?
【解决方案2】:

我认为您无法通过这项工作来生成素数。为了证明你的朋友没有找到一种很好的新方法来生成素数,我提交了: j = 2*i*(i+3)+3 是什么分配了素数,但是当你到达 i=1 然后 j=11 时,我们还没有将 5 分配为素数。由于我认为算法无法返回,因此我们错过了一个素数。

isPrime 也被初始化为 n/2+1 的大小,所以我们甚至没有空间来收集我们正在寻找的数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-21
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 2011-12-16
    相关资源
    最近更新 更多