java 蛮力法求素数

xe55xuns  于 2023-05-15  发布在  Java
关注(0)|答案(8)|浏览(162)

我在写一个寻找2-50之间的素数的程序时遇到了麻烦。我的程序现在发现“大部分”素数,但也包括一些非素数。我知道有更有效的方法和策略来寻找素数,但我试图首先通过每一种可能性,然后再进入更有效的策略。现在程序的编写方式,如果它找到了一个素数,它会多次打印它,而我只想打印一次。我的程序在概念上是正确的,还是我的理论有缺陷。为什么我的程序主要是寻找素数,但抛出一些非素数?为什么我的程序会多次打印质数?
这是我解决这个问题的方法。
1.创建一个for循环来表示2-50之间的潜在素数。用变量“i”表示这些可能的素数。这个循环将从50开始倒数。
1.因为一个数只有在除了它自己和1之外没有其他可整除数时才是质数,所以我想创建一个内部for循环来将i除以2和i-1之间的所有可能的数,看看这些数中是否有任何一个能整除i。用变量j表示这些可能的除数。如果在任何一点,j被i整除,它不是一个质数,所以我希望我的内部循环退出。
1.如果i被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 */
     }
bqf10yzr

bqf10yzr1#

你犯了两个错误。第一个在@托马斯的评论中解释,第二个在@rolfl的评论中解释。我在这里更正了两个:

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

注意:我使用以下代码验证了解决方案(在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);
        }
    } 
}

**编辑:**为了您的理解,您的主要问题是这里的逻辑:

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

您只检查了一种可能性就打印了i
例如,以i = 7为例。你必须测试i % j是否为j = 6,5,4,3和2,然后才能说i是素数。您不能像您已经做的那样,只针对j = 6测试i % j。要做到这一点,println语句应该在for循环之后,而不是嵌套在循环内部,这样就可以首先测试j的所有可能值。

**编辑2:**响应

巧合的是,赋值的第一部分是编写一个 predicate 方法,如果数字是素数,则返回true,如果不是素数,则返回false,使用暴力策略。作业的第二部分是找到一个更有效的方法,并重新工作作业的第一部分以更有效。我试着用两个for循环来解决这个问题,看看我是否能做到。它可以只用两个for循环w/o标签和继续,因为我的书还没有涵盖?
试试这样的方法:

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

7nbnzgx92#

第二个循环(内部循环)中有一个bug。
您应该递增j而不是i ....也就是说,内环应该是

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

而不是

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

0kjbasz63#

你正确地观察到,如果一个数i可以被一个数j整除,那么i % j == 0
但是,每次你找到一个i % j >= 0的情况时,你就打印了i--这并不意味着i是质数,因为可能还有其他的j可以被i整除。
相反,你应该首先检查所有的j,只有当它们都没有给你== 0时,你才应该考虑i质数。你可以使用一个初始值为true的布尔变量isPrime,但是一旦内部for循环找到一个ji可以被其整除,它就会设置为false

wljmcqd8

wljmcqd84#

if语句:

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

将打印每一个没有被j数整除的数字,并且你想要打印的数字不是那些从一个减法中得到不同于0的除法值的数字,而是所有减法。
另外,更快的解决方案是采用潜在素数的布尔数组,并像这样循环。

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")
}
zlwx9yxi

zlwx9yxi6#

你的代码有三个问题:

  • 在内部循环中,您正在增加i,而不是增加j
  • 你只要打印出i % j >= 1,但是下一个j可能会整除i,因此i不是素数。
  • 你应该在sqrt(i)处停止内部循环,以避免无用的测试。

下面是代码的更正版本:

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 */
3htmauhk

3htmauhk7#

这段代码应该打印出质数。最初的假设是每个>= 2的整数都是素数(布尔数组中为真)。在遍历数组时,如果发现该数字是素数,则通过在布尔数组中将其设置为false来删除该数字的倍数(因为它们不是素数)。最后,布尔数组中为真的数字将仅为素数。
时间复杂度:时间复杂度O(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();
    }
}
vnzz0bqm

vnzz0bqm8#

抱歉在这里吹毛求疵,但为什么你们都在for循环中使用后递增运算符?你知道i和i的区别吗?

int var1 = 5;
int var2 = 5;

int result1 = ++var1;  // Pre-increment: first increment var1 to 6, then assign to result1
int result2 = var2++;  // Post-increment: first assign var2 to result2, then increment var2 to 6

System.out.println("Pre-increment: " + result1 + ", var1: " + var1);  // Output: Pre-increment: 6, var1: 6
System.out.println("Post-increment: " + result2 + ", var2: " + var2);  // Output: Post-increment: 5, var2: 6

相关问题