看了几个实现并发现,想知道为什么从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 + " ");
}
答案 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
现在,一个观察结果: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:
和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;
}