简体   繁体   中英

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? Thanks.

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*n, has a smaller factor than m, eg. n, for which we have already marked it as composite.

This works for prime or composite n, for prime n, we set during the cycle when m=n.

For composite n: We know that any integer > 1 is representable as a product of prime factors. One of these prime factors is the smallest prime factor of n, we'll call this s. Since s is a prime factor of n, we can express n as s*r, for some r. This also means that m*n is m*s*r. s < m as n < m and s < n. We know that r has no prime factors smaller than s, as it was defined this way. 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

Lets take a number and factorize it: eg. 120

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

Now, one observation: sqrt(120) = 11 (taking floor)

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 .

Now lets factorize 36:

  • 1 x 36
  • 2 x 18
  • 3 x 12
  • 4 x 9
  • 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.

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. 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. 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.

#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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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