简体   繁体   English

使用Eratosthenes筛子生成k个素数

[英]generating k prime numbers using Sieve of Eratosthenes

Looked through a few implementation and found, wondering why start iteration from k = m * m is safe? 仔细研究了几个实现,发现为什么从k = m * m开始迭代是安全的? Thanks. 谢谢。

http://www.algolist.net/Algorithms/Number_theoretic/Sieve_of_Eratosthenes http://www.algolist.net/Algorithms/Number_theoretic/Sieve_of_Eratosthenes

public void runEratosthenesSieve(int upperBound) {
      int upperBoundSquareRoot = (int) Math.sqrt(upperBound);
      boolean[] isComposite = new boolean[upperBound + 1];
      for (int m = 2; m <= upperBoundSquareRoot; m++) {
            if (!isComposite[m]) {
                  System.out.print(m + " ");
                  for (int k = m * m; k <= upperBound; k += m)
                        isComposite[k] = true;
            }
      }
      for (int m = upperBoundSquareRoot; m <= upperBound; m++)
            if (!isComposite[m])
                  System.out.print(m + " ");
}

Every composite number less than m*m that m is a factor of, eg. 每个小于m * m的复合数字,其中m是一个因数,例如。 m*n, has a smaller factor than m, eg. m * n具有比m小的因数,例如。 n, for which we have already marked it as composite. n,我们已经将其标记为复合。

This works for prime or composite n, for prime n, we set during the cycle when m=n. 这适用于素数n或合成n,对于素数n,我们在循环中m = n时设置。

For composite n: We know that any integer > 1 is representable as a product of prime factors. 对于复合n:我们知道任何大于1的整数都可以表示为素因数的乘积。 One of these prime factors is the smallest prime factor of n, we'll call this s. 这些素数之一是n的最小素数,我们称它为s。 Since s is a prime factor of n, we can express n as s*r, for some r. 由于s是n的素数,对于某些r,我们可以将n表示为s * r。 This also means that m*n is m*s*r. 这也意味着m * n是m * s * r。 s < m as n < m and s < n. s <m,因为n <m和s <n。 We know that r has no prime factors smaller than s, as it was defined this way. 我们知道,r的质数没有小于s的质数,就像这样定义的。 So s must be be the smallest prime factor of m*s*r, so we set its iscomposite flag during the cycle for m=s 因此s必须是m * s * r的最小素数,因此我们在周期中将其iscomposite标志设置为m = s

Lets take a number and factorize it: eg. 让我们取一个数字并将其分解: 120 120

  • 1 x 120 1 x 120
  • 2 x 60 2 x 60
  • 3 x 40 3 x 40
  • 4 x 30 4 x 30
  • 5 x 24 5 x 24
  • 6 x 20 6 x 20
  • 8 x 15 8 x 15
  • 10 x 12 10 x 12

Now, one observation: sqrt(120) = 11 (taking floor) 现在,有一个观察结果:sqrt(120)= 11(取地板)

Now, next observation, each of the above factors have one thing in common, ie. one of the factors is less than 11 and other is greater than 11 现在,接下来的观察中, each of the above factors have one thing in common, ie. one of the factors is less than 11 and other is greater than 11 each of the above factors have one thing in common, ie. one of the factors is less than 11 and other is greater than 11 . each of the above factors have one thing in common, ie. one of the factors is less than 11 and other is greater than 11

Now lets factorize 36: 现在让因数分解为36:

  • 1 x 36 1 x 36
  • 2 x 18 2 x 18
  • 3 x 12 3 x 12
  • 4 x 9 4 x 9
  • 6 x 6 6 x 6

and sqrt(36) = 6. Again we can do a similar observation, that, each one of the factors have one number less than 6 and other greater, except 6 x 6 , since 36 is a square. 和sqrt(36)=6。同样,我们可以做一个类似的观察,因为36是平方,所以每个因子的个数均小于6,而除6 x 6外,其他个数均更大。

So, we can easily deduce this: 因此,我们可以轻松推断出这一点:

For any number, if it is not a prime number, we can always find (at least) one of its factor, if we go to its square root. 对于任何数字,如果它不是质数,那么我们只要找到其平方根,就总是可以找到(至少)一个因数。

So, to reduce complexity, we need to go till the square root of every number in the range, so, sqrt(upperBound) is enough for outer loop. 因此,为了降低复杂度,我们需要遍历该范围内每个数字的sqrt(upperBound) ,因此sqrt(upperBound)对于外部循环就足够了。 That is because, if any number is not marked composite by then, it will never be because we have considered all possible divisors that can be. 这是因为,如果到那时还没有标记任何数字,那将永远不会是因为我们已经考虑了所有可能的除数。

EDIT: 编辑:

Also, this implementation of sieve is not most optimized that can be. 而且,这种筛子的实现方法并不是可以most optimized Not in terms of asymptotic complexity, but you can do things to reduce few operations. 并非就渐进复杂性而言,您可以做一些事情以减少一些运算。 I'll add my implementation of sieve in c++, which calculates all primes till MAX. 我将在c ++中添加sieve的实现,该实现将计算所有素数直到MAX。

#define MAX 1000000
#define I int
#define FOR(i,a,b) for(i=a;i<b;i++)
I p[MAX]={1,1,0};            //global declaration
I prime[MAX/10]={2};         //global declaration
void sieve()
{
    I i,j,k=1;
    for(i=3;i*i<=MAX;i+=2)
    {
        if(p[i])
            continue;
        for(j=i*i;j<MAX;j+=2*i)
            p[j]=1;
    }
    for(i = 3; i < MAX; i+=2)
    {
        if(!p[i])
            prime[k++]=i;
    }
    return;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM