简体   繁体   English

在java中打印素数

[英]printing Prime numbers in java

This Java code prints out prime numbers between 2-100.此 Java 代码打印出 2-100 之间的素数。

And this works fine.这很好用。

This code is not done by me.这段代码不是我做的。

But I am trying to figure out what is happening with this code.但我试图弄清楚这段代码发生了什么。

Can anyone tell me what is happening after the second (for) loop?谁能告诉我第二个(for)循环之后发生了什么?

class primenumbers{
    public static void main(String args[]) 

    {    
        int i, j; 
        boolean isprime; 

        for(i=2; i < 100; i++) { 
            isprime = true;  

            // see if the number is evenly divisible 
            for(j=2; j <= i/j; j++) 
                // if it is, then its not prime 
                if((i%j) == 0) isprime = false; 

            if(isprime) 
                System.out.println(i + " is prime."); 
        }
    }
}

Outer (first) loop enumerates all numbers in [2,100).外部(第一个)循环枚举 [2,100) 中的所有数字。

Inner (second) loop checks if a current number from the first loop is dividable by anything.内部(第二个)循环检查来自第一个循环的当前数字是否可以被任何东西整除。

This check is done using % (remainder): (i%j)==0 when remainder of division i by j is 0 .此检查使用% (remainder): (i%j)==0i除以j的余数为0时完成。 By definition when remainder is zero i is dividable by j and therefore is not a prime : isprime=false .根据定义,当余数为零时, i可被j整除,因此不是素数: isprime=false


You only need to check in [2,i/j] because you only need to check up to sqrt(i) (explanation in the last section).你只需要检查[2,i/j]因为你只需要检查到sqrt(i) (上一节中的解释)。

Having said that the inner loop can be re-written as:话虽如此,内部循环可以重写为:

...
int s = sqrt(i);
for(j=2; j <= s; j++)
...

however sqrt is more expensive than division, therefore it's better to rewrite j<=sqrt(i) as (squaring both sides) j^2 < i and j*j<i and j<i/j .但是sqrt比除法更昂贵,因此最好将j<=sqrt(i)重写为(两边平方) j^2 < ij*j<ij<i/j When j is big enough j*j might overflow therefore both sides were divided by j in the final step.j足够大时, j*j可能会溢出,因此在最后一步中双方都被j除。


Explanation of sqrt(i) taken from here: Why do we check up to the square root of a prime number to determine if it is prime? sqrt(i)的解释取自这里: 为什么我们要检查素数的平方根以确定它是否为素数?

if i is not prime, then some x exists so that i = x * j .如果i不是素数,则存在一些x使得i = x * j If both x and j are greater than sqrt(i) then x*j would be greater than i .如果xj都大于sqrt(i)x*j将大于i

Therefore at least one of those factors (x or j) must be less than or equal to the square root of i , and to check if i is prime, we only need to test for factors less than or equal to the square root.因此,其中至少一个因子(x 或 j)必须小于或等于i的平方根,并且要检查i是否为素数,我们只需要测试小于或等于平方根的因子。

This is a modification of the Sieve of Eratosthenes.这是对埃拉托色尼筛法的改进。

First, I'll just summarize what the sieve of Eratosthenes does, you can skip to the last paragraph if you already know this.首先,我将总结一下 Eratosthenes 的筛子的作用,如果您已经知道这一点,可以跳到最后一段。 The sieve of Eratosthenes algorithm loops through a certain boundary of numbers. Eratosthenes 算法的筛子循环穿过某个数字边界。 (Say 2 - 100). (比如说 2 - 100)。 For every number it loops through, it cancels out multiples, for example, since 2 is a prime number (true), all multiples of 2 are not (They are false).对于它循环的每个数字,它都会抵消倍数,例如,因为 2 是质数(真),所以 2 的所有倍数都不是(它们是假的)。 Same for 3, 5, and so on; 3、5 等相同; and the algorithm skips every predetermined non-prime number.并且该算法跳过每个预定的非质数。 Therefore, a simulation of the algorithm would be:因此,该算法的模拟将是:

2 ---prime number... cancels out 4, 6, 8, 10, 12....
3 ---prime number... cancels out 6, 9, 12, 15, 18...
4 --- ALREADY CANCELLED OUT... Skip
5 --- prime number... cancels out 10, 15, 20, 25...
6 --- ALREADY CANCELLED OUT... Skip

The numbers not cancelled are therefore the prime numbers.因此,未被取消的数字是质数。 You can also read this for more information: http://www.geeksforgeeks.org/sieve-of-eratosthenes/您还可以阅读此内容以获取更多信息: http ://www.geeksforgeeks.org/sieve-of-eratosthenes/

Now, to your question, your algorithm loops through the list of numbers.现在,对于您的问题,您的算法循环遍历数字列表。 For each number(say x), it checks if any of the previous numbers looped through (i / j) is a factor of the x.对于每个数字(比如 x),它检查循环通过 (i / j) 的任何先前数字是否是 x 的因子。 The reason why i/j is used as the boundary for the second for loop is for efficiency.之所以使用i/j作为第二个 for 循环的边界,是为了提高效率。 If you're checking if 10 (for example) is a prime number, there's no need to check whether 6 is a factor.如果您正在检查 10(例如)是否是质数,则无需检查 6 是否是一个因数。 You can conveniently stop at n/(n/2).您可以方便地停在 n/(n/2)。 That's what that part is trying to achieve.这就是该部分试图实现的目标。

The first loop just for generating numbers from 2 to 100.第一个循环仅用于生成从 2 到 100 的数字。

The second loop tries to find if the number is divisible by any other number.第二个循环尝试查找该数字是否可以被任何其他数字整除。 Here we try to divide a the number with a set of numbers (2 to prime_index).在这里,我们尝试将一个数字与一组数字(2 到 prime_index)相除。

Let's say the number is 10 , the prime index is 10/2 = 5 for first iteration(j = 2).假设数字是10 ,第一次迭代(j = 2)的素数索引是10/2 = 5 Which means, if the number 10 is not divisible by any number between 2 and 5, it's a prime number.这意味着,如果数字10不能被 2 到 5 之间的任何数字整除,则它是质数。 It's divisible by 2 itself making it a non prime number.它本身可以被2整除,使其成为非质数。

Let's say the number is 9, now the prime index is 9/2 = 4 for first iteration(j = 2).假设数字是 9,现在第一次迭代(j = 2)的素数索引是9/2 = 4 Now, 9 % 2 gives 1 as reminder.现在, 9 % 2给出 1 作为提醒。 So, loop continues for second iteration (j = 3).因此,循环继续进行第二次迭代(j = 3)。 Now the prime index is 9/3 = 3 ( Note here the prime index value is reduced from 4 to 3 ) So, now if the number is not divisible by 3 , its decided as a prime number.现在素数索引是9/3 = 3注意这里素数索引值从 4 减少到 3 )所以,现在如果数字不能被3整除,则它被确定为素数。

So, for every iteration, the prime index will reduce, making the number of iterations reduced.因此,对于每次迭代,素数索引都会减少,从而减少迭代次数。

Example for Number 97,
j = 2, prime index = 97/2 = 48 (no of iterations for loop)
j = 3, prime index = 97/3 = 32 (no of iterations for loop)
j = 4, prime index = 97/4 = 24 (no of iterations for loop)
j = 5, prime index = 97/5 = 19 (no of iterations for loop)
j = 6, prime index = 97/6 = 16 (no of iterations for loop)
j = 7, prime index = 97/7 = 13 (no of iterations for loop)
j = 8, prime index = 97/8 = 12 (no of iterations for loop)
j = 9, prime index = 97/9 = 10 (no of iterations for loop)
j = 10, prime index = 97/10 = 9 (loop exits as condition failed 10 <= 9 and declares 97 as a prime number)

Now, here the loop actually took 10 iterations instead of the proposed 48 iterations.现在,这里的循环实际上进行了 10 次迭代,而不是建议的 48 次迭代。

Let's modify the code for better understanding.让我们修改代码以便更好地理解。

public static void main(String args[]) {    
        // Number from 2 to 100
    for(int i=2; i < 100; i++) { 
       if (isPrimeNumber(i)) {
            System.out.println(i + " is prime");
       }
    }
}

Now, lets see a method isPrimeNumberNotOptimized() which is not optimized.现在,让我们看一个未优化的方法isPrimeNumberNotOptimized()

private static boolean isPrimeNumberNotOptimized(int i) {
    for(int j=2; j <= i/2; j++) {
        // if it is, then its not prime 
        if((i%j) == 0) {
            return false;
        }
    }
    return true; 
}

And, another method isPrimeNumberOptimized() which is optimized with prime index.而且,另一种方法是isPrimeNumberOptimized() ,它使用素数索引进行了优化。

private static boolean isPrimeNumberOptimized(int i) {
    for(int j=2; j <= i/j; j++) {
        // if it is, then its not prime 
        if((i%j) == 0) {
            return false;
        }
    }
    return true; 
}

Now, both methods will run and print the prime numbers correctly.现在,这两种方法都将正确运行并打印素数。

But, the optimized method will decide 97 is a prime number at 10th iteration.但是,优化的方法将在第 10 次迭代时确定97是素数。

And, the non-optimized method will decide the same in 48th iteration.并且,未优化的方法将在第 48 次迭代中做出相同的决定。

Hope, you understand it now.希望,你现在明白了。

FYI: prime index is the number we used for calculation.仅供参考:素数指数是我们用于计算的数字。 Such that if a number is not divisible between 2 & the derived prime index, its a prime number这样,如果一个数不能在 2 和派生的素数索引之间整除,则它是素数

public class PrimeNumber {公共类 PrimeNumber {

//check prime number
public static boolean prime(int number){
    boolean isPrime=true;

    for(int i=number-1;i>1;i--){

        if(number%i==0){
            isPrime=false;
            System.out.println(i);
            break;
        }
    }

   return isPrime;
}

public static boolean getPrimeUsingWhile(int number){
    boolean isPrime=true;
    Integer temp=number-1;
    while (temp>1){

        if(number%temp==0){
            isPrime=false;
            break;
        }

        temp--;
    }

    return isPrime;
}
//print primenumber given length
public static List<Integer> prinPrimeList(){

    boolean isPrime=true;
    List<Integer> list=new ArrayList<>();
    int temp=2;
    while (list.size()<10){

        for(int i=2;i<temp;i++){

            if(temp%i==0){
                isPrime=false;
                break;
            }else{
                isPrime=true;
            }

        }

        if(isPrime){list.add(temp);}
        temp++;
    }


    return list;
}


public static void main(String arg[]){

    System.out.println(prime(3));
    System.out.println(getPrimeUsingWhile(5));
    System.out.println(Arrays.toString(prinPrimeList().toArray()));
}

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM