public class Main {
public static void main(String args []){
long numberOfPrimes = 0; //Initialises variable numberOfPrimes to 0 (same for all other variables)
int number = 1;
int maxLimit = 10000000;
boolean[] sieve = new boolean[maxLimit]; //creates new boolean array called sieve and allocates space on the
//stack for this array which has maxLimit spaces in it
for ( int i = 2; i < maxLimit; i++ ) { //for statement cycling from 2 to 10000000, does not execute the rest
//of the block if the boolean value in the array is true
if ( sieve[i] == true ) continue;
numberOfPrimes++; //otherwise it increments the number of prime numbers found
if ( numberOfPrimes == 10001 ) { //if 10001st prime number is found, break from loop
number = i;
break;
}
for ( int j = i+i; j < maxLimit; j += i ) //do not understand the point of this loop logically
sieve[j] = true; //testing if the value in the array is true again?
}
System.out.println("10001st prime: "+ number);
}
}
我真的不明白这个节目中发生了什么,并希望有人可以向我解释一下?我已经评论了导致我麻烦的具体线路/我理解的线路。非常感谢您的帮助! :)
答案 0 :(得分:7)
熟悉Eratosthenes' Sieve算法。维基百科甚至还有GIF动画演示了这个过程。而你的代码只是一个简单的实现。
答案 1 :(得分:2)
是的,这是Eratosthenes'Sieve的基本实现。有很多方法可以改进它,但我们首先要讨论基本原理。
您正在做的是创建一个布尔值数组。数组中的INDEX表示我们正在测试的数字,看它是不是素数。
现在,您将开始检查每个数字,看看它是否是素数。首先,素数的定义是“所有数字本身都可以被整除,而1则没有分数”。
for ( int i = 2; i < maxLimit; i++ )
你从INDEX 2(数字3)开始,因为根据你的定义,1和2总是素数。 (有些定义说1不是素数)。
if ( sieve[i] == true ) continue;
如果某个数字之前已被标记为非素数,我们不会为当前的迭代而烦恼。
numberOfPrimes++;
if ( numberOfPrimes == 10001 ) {
number = i;
break;
}
如果我们目前的INDEX没有被标记为素数,那么它必须是1,所以我们增加了我们找到的素数。我假设的下一段代码是程序要求的一部分,该程序要求如果找到10001个素数,程序必须退出。如果你真的想检查最多数量的素数而不是特定数量的素数,那么这部分就可以省略。
for ( int j = i+i; j < maxLimit; j += i )
sieve[j] = true;
这是筛子真正的魔力开始的地方。从素数的定义来看,如果一个数可以被除了它本身以外的任何东西整除,那么它就不能成为素数。因此,对于我们发现的任何新数,我们可以将它的所有因子都标记为不是素数。例如,for循环的第一次迭代,我们从3开始。因为sieve [2]是假的(之前没有访问过),所以它是一个素数(AND 3 IS A PRIME!)。然后,3的所有其他因素不能是素数。上面提到的for循环遍历整个筛子,并将3的所有因子都标记为假。所以这个循环会做:筛[5] =真;筛[8] =真......直到筛子结束。
现在,当您达到大于最初定义的最大值的第一个数字时,您可以确定任何具有因子的数字已被标记为不是素数。你最终得到的是一个布尔数组,其中每个标记为false的索引代表一个素数。
您可以在维基百科上获得更好的描述,但这是它的主旨。希望它有所帮助!
答案 2 :(得分:1)
for ( int j = i+i; j < maxLimit; j += i ) //dont understand the point of this loop logically
sieve[j] = true; //testing if the value in the array is true again ?
这不是测试,而是设置。此循环设置数组中的所有项目的索引倍数为i
到true
。当i
为2时,则第4,6,8 ...项将设置为true
。当i
为3时,项目6,9,12 ...将设置为true
,依此类推。
正如您可以通过第一个if
推断,
if ( sieve[i] == true ) continue;
... true
的所有项目都与非素数相对应。
答案 3 :(得分:1)
我发现理解某事的最简单方法就是解构它。因此,让我们进行几次循环,是吗?
- 9999998值保持不变 -
i = 2
sieve[2]
是false
,所以我们继续进行当前的迭代
numberOfPrimes = 1
因此我们继续处理
将{2}中的每个倍数设置为true
中的sieve[]
。
- 9999997值保留 -
i = 3
sieve[3]
是false
,所以我们继续进行当前的迭代
numberOfPrimes = 2
因此我们继续处理
将{3}中的每3的倍数设置为true
中的sieve[]
。
- 9999996值保留 -
i = 4
sieve[4]
是true
(从第一次迭代开始)。跳到下一次迭代。
等...但在这种情况下,月亮不会崩溃到Termina。
答案 4 :(得分:0)
有问题的循环不是检查的真值,它是设置的真值。
它经历了素数的每个倍数,并将其标记为非素数,直到maxLimit
。您会注意到代码中没有其他数学来确定什么是素数,什么不是。
答案 5 :(得分:0)
这是找到1和最大限制之间的素数的算法。
并且第二个添加的循环是对于可被任何其他数字整除的数字生效。因此,对于第一个外部循环,所有可被2 ll整除的数字都设置为true然后可以被3整除然后依此类推...而布尔数组包含false的数字是素数