有人可以解释这个实现如何工作?还有,它会变得更好吗?怎么样?

时间:2010-10-25 17:08:30

标签: java algorithm

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

我真的不明白这个节目中发生了什么,并希望有人可以向我解释一下?我已经评论了导致我麻烦的具体线路/我理解的线路。非常感谢您的帮助! :)

6 个答案:

答案 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 ?

这不是测试,而是设置。此循环设置数组中的所有项目的索引倍数为itrue。当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的数字是素数