使用Eratosthenes筛选生成k素数

时间:2015-10-08 07:36:48

标签: java algorithm primes

看了几个实现并发现,想知道为什么从k = m * m开始迭代是安全的?感谢。

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 + " ");
}

2 个答案:

答案 0 :(得分:3)

每个小于m * m的复合数,m是因子,例如。 m * n,具有小于m的因子,例如。 n,我们已将其标记为复合。

这适用于素数或复合n,对于素数n,我们在周期中设置m = n。

对于复合n:我们知道任何整数&gt; 1表示为素因子的乘积。其中一个主要因素是n的最小素因子,我们称之为s。由于s是n的主要因子,对于某些r,我们可以将n表示为s * r。这也意味着m * n是m * s * r。 s&lt; m为n&lt; m和s&lt; ñ。我们知道r没有小于s的素因子,因为它是以这种方式定义的。所以s必须是m * s * r的最小素因子,所以我们在m = s的周期内设置它的iscomposite标志

答案 1 :(得分:2)

让我们拿一个数字并将其分解:例如。 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

现在,一个观察结果:sqrt(120)= 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

现在让我们分解36:

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

和sqrt(36)= 6.我们再次进行类似的观察,即每个因子都有一个小于6的数字和其他更大的数字,除了6 x 6,因为36是一个正方形。< / p>

因此,我们可以很容易地推断出这一点:

  

对于任何数字,如果它不是素数,如果我们去平方根,我们总能找到(至少)其中一个因子。

因此,为了降低复杂性,我们需要直到范围内每个数字的平方根,因此,sqrt(upperBound)足以用于外部循环。那是因为,如果到那时任何数字都没有标记为复合数,那么它永远不会是因为我们已经考虑了所有可能的除数。

编辑:

此外,筛选的实现不是most optimized。不是渐近复杂性,而是你可以做一些事情来减少一些操作。我将在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;
}