【问题标题】:Next Prime number Java only working with certain numbers下一个质数 Java 仅适用于某些数字
【发布时间】:2014-02-27 23:15:43
【问题描述】:

此功能仅适用于某些数字,但对于 15 或 5,它不会给我正确的下一个素数。

public static int nextPrime(int n) {
    boolean isPrime = false;
    int m = (int) Math.ceil(Math.sqrt(n));
    int start = 3;
    if (n % 2 == 0) {
        n = n + 1;
    }
    while (!isPrime) {
        isPrime = true;
        for (int i = start; i <= m; i = i + 2) {
            if (n % i == 0) {
                isPrime = false;
                break;
            }
        }
        if (!isPrime) {
            n = n + 2;
        }
    }
    return n;
}

【问题讨论】:

  • 您的代码适用于我,适用于 15 和 5。
  • 尝试为变量使用更长的名称,这会使代码更具可读性和更容易回答。 ipotentialFactormmaxFactor
  • 你能提供输入和预期输出吗?
  • 你应该把这个提交给 CodeReview。

标签: java primes


【解决方案1】:

你不需要上升到 sqrt(n),你需要上升到你正在评估的 sqrt(number)

例如考虑你通过 n = 5

它将从 3 开始循环,它将在 4 结束循环,这不是您找到下一个素数所需要的

外循环 从 n + 1 开始,直到找到素数 内循环 你应该从 3 和 sqrt(numberUnderIteration) 开始

【讨论】:

  • 这应该是一条评论。除非你扩展它。
  • @user 查看解释版本
【解决方案2】:

您将边界设置为原始数字的平方根。为了让您检查每个下一个数字是否有效,您需要在 n 值更改时重新计算边界。所以,把 int m = (int) Math.ceil(Math.sqrt(n)); 放在你的 while 循环中。

在开始任何计算之前,您还需要将 n 增加 1,否则它将接受 n 本身作为质数(如果它是 1)。例如,nextPrime(5) 将返回 5,因为它通过了条件。

最后,您不需要在 while 循环结束时将 n 增加 2,因为如果您在偶数上,它会中断(继续将 2 加到偶数将始终是偶数)。我已经评论了我更改的代码部分:

public static int nextPrime(int n) {
    boolean isPrime = false;

    int start = 2; // start at 2 and omit your if statement

    while (!isPrime) {
        // always incrememnt n at the beginning to check a new number
        n += 1;
        // redefine max boundary here
        int m = (int) Math.ceil(Math.sqrt(n));

        isPrime = true;
        // increment i by 1, not 2 (you're skipping numbers...)
        for (int i = start; i <= m; i++) {
            if (n % i == 0) {
                isPrime = false;
                break;
            } 
        }
        // you don't need your "if (!isPrime)..." because you always increment
    }
    return n;
}

public static void main(String[] args) {

    System.out.println(nextPrime(15)); // 17
    System.out.println(nextPrime(5)); // 7
    System.out.println(nextPrime(8)); // 11
}

【讨论】:

    【解决方案3】:

    您需要在 for 循环中计算 m。

      while (!isPrime) {
         isPrime = true;
          int m = (int) Math.ceil(Math.sqrt(n));
    
         // do other stuff
    

    【讨论】:

      【解决方案4】:

      您的代码可以正常工作,除非将素数作为输入,您的方法会返回输入本身。

      例如,如果 5 是您的输入,nextPrime(5) 返回 5。如果您希望在这种情况下返回 7(5 之后的下一个素数)。

      只需在方法的开头添加n=n+1;。希望这会有所帮助

      【讨论】:

        【解决方案5】:

        只是为了好玩,我编写了一个快速的 Prime 类来跟踪已知素数,从而极大地提高了查找多个大素数的性能。

        import java.util.ArrayList;
        
        public class Primes {
        
            private static ArrayList<Integer> primes = new ArrayList<Integer>();
        
            public static int nextPrime(int number){
        
                //start it off with the basic primes
                if(primes.size() == 0){
                    primes.add(2);
                    primes.add(3);
                    primes.add(5);
                    primes.add(7);
                }
        
                int idx = primes.size()-1;
                int last = primes.get(idx);
        
                //check if we already have the prime we are looking for
                if(last > number){
                    //go to the correct prime and return it
                    boolean high = false;
                    boolean low = false;
                    int prevIdx = 0;
                    int spread = 0;
                    //keep finagling the index until we're not high or low
                    while((high = primes.get(idx-1) > number) || (low = primes.get(idx) <= number)){
                        spread = Math.abs(prevIdx-idx);
                        //because we always need to move by at least 1 or we will get stuck
                        spread = spread < 2 ? 2: spread;
                        prevIdx = idx;
                        if(high){
                            idx -= spread/2;
                        } else if(low){
                            idx += spread/2;
                        }
                    };
                    return primes.get(idx);
                }
        
                /*FIND OUR NEXT SERIES OF PRIMES*/
        
                //just in case 'number' was prime
                number++;
        
                int newPrime = last;
                //just keep adding primes until we find the right one
                while((last = primes.get(primes.size()-1)) < number){
                    //here we find the next number
                    newPrime += 2;
                    //start with the assumption that we have a prime, then try to disprove that
                    boolean isPrime = true;
                    idx = 0;
                    int comparisonPrime;
                    int sqrt = (int) Math.sqrt(newPrime);
                    //make sure we haven't gone over the square root limit- also use post-increment so that we use the idx 0
                    while((comparisonPrime = primes.get(idx++)) <= sqrt){
                        if(newPrime % comparisonPrime == 0){
                            isPrime = false;
                        }
                    }
                    if(isPrime){
                        primes.add(newPrime);
                    }
                }
        
                return last;
            }
        }
        

        这是测试:

        public class Test {
        
            public static void main(String[] args){
        
                long start;
                long end;
                int prime;
                int number;
        
                number = 1000000;
                start = System.currentTimeMillis();
                prime = Primes.nextPrime(number);
                end = System.currentTimeMillis();
                System.out.println("Prime after "+number+" is "+prime+". Took "+(end-start)+" milliseconds.");
        
                number = 500;
                start = System.currentTimeMillis();
                prime = Primes.nextPrime(number);
                end = System.currentTimeMillis();
                System.out.println("Prime after "+number+" is "+prime+". Took "+(end-start)+" milliseconds.");  
        
                number = 1100000;
                start = System.currentTimeMillis();
                prime = Primes.nextPrime(number);
                end = System.currentTimeMillis();
                System.out.println("Prime after "+number+" is "+prime+". Took "+(end-start)+" milliseconds.");      
            }
        }
        

        这会产生以下输出:

        Prime after 1000000 is 1000003. Took 384 milliseconds.
        Prime after 500 is 503. Took 10 milliseconds.
        Prime after 1100000 is 1100009. Took 65 milliseconds.
        

        如您所见,第一次迭代需要很长时间,但我们只需执行一次该操作。在那之后,对于比我们的第一个数字小的素数,我们的时间几乎减少到零(因为它只是一个查找),对于比我们的第一个数字大一点的素数(因为我们已经完成了大部分的工作)。

        编辑:使用Binary Search Algorithm 的变体更新了对现有素数的搜索。它至少将搜索时间缩短了一半。

        【讨论】:

          【解决方案6】:
          import java.util.Scanner;
          
          class Testing 
          {
              public static void main(String Ar[])
              {
                  int a = 0, i, j;
                  Scanner in = new Scanner(System.in);
                  a = in.nextInt();
                  for (j = a + 1;; j++) 
                  {
                      for (i = 2; i < j; i++) 
                      {
                          if (j % i == 0)
                          break;
                      }
                        if (i == j) 
                       {
                           System.out.println(j);
                           break;
                       }
                  }
              }
          }
          

          【讨论】:

            【解决方案7】:

            这是查找给定数字的下一个素数的完美代码。

            public class NextPrime
            {
            
                int nextPrime(int x)
                {
                    int num=x,j;
                        for( j=num+1;;j++)
                        {
                            int count=0;
            
                                for(int i=1;i<=j;i++)
                                {
                                    if(j%i==0)
                                    {
                                    count++;
                                    //System.out.println("entered");
                                    }
                                    //System.out.println(count);
                                }
                                if(count==2)
                                {
                                System.out.println(" next prime is ");
                                break;
                                }
            
                        }return j;
                }
            
                public static void main(String args[])
                {
                    NextPrime np = new NextPrime();
                    int nxtprm = np.nextPrime(9);
                    System.out.println(nxtprm);
                }
            
            }
            

            【讨论】:

              【解决方案8】:
              //I hope the following code works exactly.
              
              
              import java.util.Scanner;
              public class NextPrime {
                  public static void main(String[] args) {
                      Scanner scanner = new Scanner(System.in);
                      System.out.println("Enter a positive integer number : ");
                      int n = scanner.nextInt();
                      for (int x = n + 1;; x++) {
                          boolean isPrime = true;
                          for (int i = 2; i < x / 2; i++) {
                              if (x % i == 0) {
                                  isPrime = false;
                                  break;
                              }
                          }
                          if (isPrime) {
                              System.out.println("Next prime is : " + x);
                              break;
                          }
                      }
                  }
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-05-27
                • 2012-04-22
                • 1970-01-01
                • 1970-01-01
                • 2022-11-10
                相关资源
                最近更新 更多