简体   繁体   English

蛮力法求素数

[英]Brute force method finding prime numbers

I'm having trouble writing a program that finds the prime numbers between 2-50. 我在编写找到2-50之间的质数的程序时遇到了麻烦。 My program right now finds "mostly" prime numbers but some non-prime numbers are included. 我的程序现在可以找到“大部分”质数,但其中包含一些非质数。 I know there are way more effective methods and strategies for finding prime numbers but I'm trying to first run through every possibility before i move onto more efficient and effective strategies. 我知道可以找到更有效的方法和策略来找到素数,但是在尝试使用更有效的策略之前,我会先尝试各种可能性。 The way the program is written now if it does find a prime number it prints it multiple times when I only want it to be printed once. 如果确实找到质数,则该程序现在的编写方式将在我只希望打印一次时将其打印多次。 Is my program conceptually correct or is my rationale flawed. 我的程序在概念上是正确的还是我的原理存在缺陷。 Why does my program mostly find prime numbers but throw in some non prime numbers? 为什么我的程序大多会找到质数,却抛出一些非质数? Why does my program print the prime numbers multiple times? 为什么我的程序多次打印素数?

Here is my approach to the problem. 这是我解决问题的方法。

  1. create a for loop to represent potential prime numbers between 2-50. 创建一个for循环以表示2-50之间的潜在质数。 Represent these potential prime numbers by the variable "i". 用变量“ i”表示这些潜在质数。 This loop will count down from 50. 此循环将从50开始倒数​​。

  2. Since a number is prime only if there are no other divisible numbers besides itself and 1, i want to create a inner for loop to divide i by every possible number between 2 and i -1 to see if any of these numbers divides evenly into i. 因为仅当数字本身和1之外没有其他可除数时,数字才是质数,所以我想创建一个内部for循环,用2和i -1之间的每个可能数字除以i,以查看这些数字中是否有任何一个均等地划分为i 。 Represent these possible divisors by the variable j. 用变量j表示这些可能的除数。 If at any point j does divides evenly into i it's not a prime number so I want my inner loop to exit. 如果在任何时候j确实均分了i,它不是质数,所以我希望退出内部循环。

  3. If i gets divided by all the numbers of j and there are no numbers that divide evenly into i then that number if prime and want to print that number. 如果我除以j的所有数字,并且没有数字被i均分,那么该数字为质数并想要打印该数字。

* *

import acm.program.*;
public class PrimeNumber extends ConsoleProgram{
public void run(){

  for (int i =50; i >= 2; i--){
    for (int j= 2; j < i-1; j++){

        if (i % j >= 1){
         println(i);
         }else{
         if (i % j == 0) break;
                }
              } /*end of inner loop */  
           } /* end of for loop */

       } /* end of run method */
     } 

You made 2 mistakes. 您犯了两个错误。 The first is explained in the comment by @Thomas and the second is explained in the comment by @rolfl . 第一个在@Thomas的注释中说明,第二个在@rolfl的注释中说明 I corrected them both here: 我在这里都纠正了它们:

public class PrimeNumber extends ConsoleProgram {
    public void run() {
        for (int i = 50; i >= 2; i--) {
            boolean isPrime = true;
            for (int j = 2; j < i-1; j++) { //increment "j" not "i"
                if (i % j == 0) {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime) System.out.println(i);
        }
    } 
}

Note: I verified the solution using this code (save in your IDE as PrimeNumber.java): 注意:我使用以下代码验证了解决方案(在您的IDE中另存为PrimeNumber.java):

public class PrimeNumber {
    public static void main (String args[]) {
        for (int i = 50; i >= 2; i--) {
            boolean isPrime = true;
            for (int j = 2; j < i-1; j++) { //increment "j" not "i"
                if (i % j == 0) {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime) System.out.println(i);
        }
    } 
}

Edit: For your understanding, your main problem is the logic here: 编辑:据您了解,您的主要问题是此处的逻辑:

for (int j= 2; j < i-1; j++) {
    if (i % j >= 1) {
        println(i);

You are printing i after only checking one possibility. 您仅在检查一种可能性后才打印i

For example, take i = 7 . 例如,取i = 7 You have to test i % j for j = 6, 5, 4, 3, and 2 before you can say that i is prime. 您必须先测试i % jj = 6、5、4、3和2,然后才能说i是素数。 You can't just test i % j for j = 6 , as you have done. 您不能像已经完成的那样仅对i % j j = 6 i % jj = 6进行测试。 To do so, your println statement should come after the for loop, not nested inside of it, so you can test all the possible values of j first. 为此,您的println语句应位于for循环之后,而不是嵌套在其中,因此您可以首先测试j所有可能值。


Edit 2: In response to 编辑2:回应

Coincidentally enough, the 1st part of the assignment is to write a predicate method that returns true if the number is prime and false if it is not prime using the strategy of brute-force. 碰巧的是,赋值的第一部分是编写一个谓词方法,如果该数字为质数,则返回该谓词,如果使用强力策略则返回非质数。 The 2nd part of the assignment is to find a more efficient way and reworking the 1st part of the assignment to be more efficient. 作业的第二部分是找到一种更有效的方法,并对作业的第一部分进行重新加工以提高效率。 I was trying to solve the problem using just using two for loops to see if i could do it. 我试图通过仅使用两个for循环来解决问题,看看是否可以做到。 Can it be done with just two for loops w/o label and continue since my book has not covered that yet? 可以只用两个不带标签的for循环来完成它,然后继续进行,因为我的书还没有介绍?

Try something like this: 尝试这样的事情:

public boolean isPrime(int number) {
    for (int i = 2; i < number; i++) {
        if (number % i == 0) {
            return false; //not prime
        }
    }
    return true; //prime
}

You correctly observed that if a number i can be evenly divided by a number j , then i % j == 0 . 您正确地观察到,如果数字i可以除以数字j ,则i % j == 0

However, you're printing i every time you find a case where i % j >= 0 -- that doesn't mean however that i is prime, because there could be some other j that i can be evenly divided by. 但是,每次找到i % j >= 0的情况时,您都在打印i-这并不意味着i是质数,因为可能会有其他j可以被i平均除。

Instead, you should first go through all of your j , and only if none of them gives you == 0 , should you consider i prime. 相反,您应该首先遍历所有j ,并且只有当它们均不给您== 0 ,才应考虑i素数。 You could use a boolean variable isPrime that is initially true , but that the inner for-loop sets to false as soon as it finds a j by which i can be evenly divided. 您可以使用布尔变量isPrime ,该变量最初为true ,但是一旦找到j可以将i平均除的j ,则内部for循环将设置为false

There is a bug in your second loop (the inner loop). 您的第二个循环(内部循环)中有一个错误。

You should be incrementing j and not i .... ie the innner loop should be 您应该递增j而不是i ....即内部循环应该是

for (int j= 2; j < i-1; j++){

and not 并不是

for (int j= 2; j < i-1; i++){

This if statement: 这个if语句:

if (i % j >= 1){
         println(i);

Will print every number that is not divided by j number, and the numbers you want to print are not those that will get a value of division different from 0 from one substract but for ALL substracts. 将打印不被j数除的每个数字,并且您要打印的数字不是从一个减数获得除0的除法值的数字,而是对于所有减数。

Also the faster solution is taking the Boolean array of potentially prime numbers and looping like this. 同样,更快的解决方案是采用潜在质数的布尔数组并像这样循环。

for ( i = 2; i < sqrt(maxvalue); i ++){
            for(j = 1; j < sqrt(maxval); j++){
                  potentialy_prime[i*j]=false
            }
       }
for (potentialy_prime){
    if(potentialy_prime[i]==true)
            print(i "is prime")
}

Check out dydx's answer on this question: https://stackoverflow.com/questions/13437162/java-finding-prime-numbers . 查看dydx关于此问题的答案: https ://stackoverflow.com/questions/13437162/java-finding-prime-numbers。 Or this question: Prime number calculation fun or this one Getting the prime numbers , etc... 或这个问题:质数计算的乐趣或这一获取质数 ,等等...

There are 3 problems with your code : 您的代码有3个问题:

  • In the inner loop, you are increasing i instead of increasing j . 在内部循环中,您将增加i而不是增加j

  • You print the number as soon as i % j >= 1 , but maybe the next j will divide i , and thus i isn't prime. 您在i % j >= 1立即打印数字,但是下一个j可能会除以i ,因此i不是素数。

  • You should stop the inner loop at sqrt(i) to avoid useless tests. 您应该在sqrt(i)处停止内部循环,以避免无用的测试。

Here is a corrected version of the code : 这是该代码的更正版本:

OUTER: for (int i = 50; i >= 2; i--) {
    for (int j = 2; j <= (int) Math.sqrt(i); j++) {
        if (i % j == 0)
            continue OUTER;
        } /* end of inner loop */
    println(i);
} /* end of for loop */

This code should print out the prime numbers. 此代码应打印出素数。 Initial assumption is that every integer >= 2 is prime(true in boolean array). 最初的假设是每个大于等于2的整数都是素数(布尔数组中为true)。 while traversing through the array, if the number is found to be prime, cross out multiples of that number by setting them false in boolean array ( as they are not prime). 在遍历数组时,如果发现数字为质数,则通过在布尔数组中将它们设置为false来舍去该数字的倍数(因为它们不是质数)。 At the end the numbers having true in boolean array will be prime numbers only. 最后,布尔数组中为true的数字将仅是质数。

Time complexity : O(n log(log n)) 时间复杂度:O(n log(log n))

public class PrimesImprovement
{
    public static void main(String[] args)
    {  
        System.out.println("Printing primes from 1 to 100");
        int i;
        int j;
        //boolean prime;
        boolean[] prime_arr=new boolean[100];
        Arrays.fill(prime_arr,true); // Assumption
        prime_arr[0]=prime_arr[1]=false;  // As 0 and 1 are not prime numbers
        for ( i=2;i<prime_arr.length;i++) 
        {

            if(prime_arr[i])
            { 
                for ( j=2;i*j<prime_arr.length;j++) 
                {
                    prime_arr[i*j]=false;
                }
            }
        }

        for( i=0; i<prime_arr.length; i++)
        {
            if(prime_arr[i])
            {
                System.out.print(i+" ");
            }
        }

        System.out.println();
    }
}

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

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