簡體   English   中英

使用Eratosthenes篩子生成k個素數

[英]generating k prime numbers using Sieve of Eratosthenes

仔細研究了幾個實現,發現為什么從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 + " ");
}

每個小於m * m的復合數字,其中m是一個因數,例如。 m * n具有比m小的因數,例如。 n,我們已經將其標記為復合。

這適用於素數n或合成n,對於素數n,我們在循環中m = n時設置。

對於復合n:我們知道任何大於1的整數都可以表示為素因數的乘積。 這些素數之一是n的最小素數,我們稱它為s。 由於s是n的素數,對於某些r,我們可以將n表示為s * r。 這也意味着m * n是m * s * r。 s <m,因為n <m和s <n。 我們知道,r的質數沒有小於s的質數,就像這樣定義的。 因此s必須是m * s * r的最小素數,因此我們在周期中將其iscomposite標志設置為m = s

讓我們取一個數字並將其分解: 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 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。同樣,我們可以做一個類似的觀察,因為36是平方,所以每個因子的個數均小於6,而除6 x 6外,其他個數均更大。

因此,我們可以輕松推斷出這一點:

對於任何數字,如果它不是質數,那么我們只要找到其平方根,就總是可以找到(至少)一個因數。

因此,為了降低復雜度,我們需要遍歷該范圍內每個數字的sqrt(upperBound) ,因此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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM