【问题标题】:Optimal way to find next prime number (Java)查找下一个素数的最佳方法(Java)
【发布时间】:2017-11-21 07:13:11
【问题描述】:

我被要求编写一个程序来以最佳方式找到下一个素数。我写了这段代码,但我找不到最佳答案。有什么建议吗?

public  static int nextPrime(int input) {

    input++;
    //now find if the number is prime or not

    for(int i=2;i<input;i++) {
        if(input % i ==0  ) {
            input++;
            i=2;
        }
        else{
            continue;
        }
    }
    return input;
}

【问题讨论】:

  • 我对问题陈述中“最佳”一词的意图感到困惑。这是字面上指定的内容,还是“高效”的释义?
  • 我可以作弊吗?我认为只有 15M 的 32 位素数...可以将它们放在排序列表中...
  • 我认为是 O(n^2)
  • Miller-Rabin 是 O(k log3n),因此为每个候选者增加它最多可能是 O(kn log^3n),(对于常数 k,有 1/2^k 的机会错了)
  • 我要改变我对 O(n^2)...O(n*k) 的看法,其中 k 是input 附近区域中素数之间的平均距离.我认为这有一些近似值。

标签: java algorithm


【解决方案1】:
public int nextPrime(int input){
  int counter;
  input++;
  while(true){
    int l = (int) sqrt(input);
    counter = 0;
    for(int i = 2; i <= l; i ++){
      if(input % i == 0)  counter++;
    }
    if(counter == 0)
      return input;
    else{
      input++;
      continue;
    }
  }
}

无需检查输入号码。检查一个数字的平方根就足够了。抱歉,我不记得定理的名称。在这里,我们正在增加下一个素数的输入。

这个解的时间复杂度 O(n^(3/2))。

【讨论】:

  • 一个非常低效的例子。将 sqrt(input) 移到循环之外,以便只计算一次。当你找到一个除数时,跳出内循环。
  • 好观察@nicomp,你能帮我改一下吗?
  • 不。自己进行更改。
  • 绝对是。您从去年的另一个 SO 答案中复制/粘贴。不酷。
  • 不是“标准”代码。你把它归功于它,这就是我投反对票的原因。
【解决方案2】:

@Ephraim - 我用“while”循环替换了递归代码。它运行得更快。

int nextPrime(int M) { while(!isPrime(++M)) // no need ++M; as I already added in the isPrime method's parameter. return M; } boolean isPrime(int M) { for(int i = 2; i <= M; i++) if(M % i == 0) return false; return true; }


@Scott Parent-我已经测试了递归代码; “while”循环和蒸汽代码(IntStream 和 LongStream)——Stream 的代码运行缓慢,非常缓慢。 示例:
输入值:60000000000
输出:60000000029
递归算法经过的时间 = 7 毫秒
输出:60000000029
遍历算法所用的时间 = 4 毫秒
输出:60000000029
LongStream.range(2, number).noneMatch(...) 算法的经过时间 = 615825 毫秒

如果我使用 IntStream - 最大整数数的经过时间约为 230 毫秒。这太慢了。
nextPrime(int n) 中的“while”循环对于最大整数运行 1-4 毫秒,但对于 600000000000 输入值使用 LongStream - 结果我在 1 小时内看不到。 我现在正在运行 600000000000 长号码:
递归算法经过的时间 = 36 毫秒
输出:60000000029
遍历算法所用时间 = 27 毫秒
输出:60000000029
LongStream.range(2, number).noneMatch(...) 的经过时间
它仍然运行超过 58 分钟,但还没有完成。

【讨论】:

    【解决方案3】:
    long n = 12345;
    BigInteger b = new BigInteger(String.valueOf(n)); 
    long res = Long.parseLong(b.nextProbablePrime().toString()); 
    
    System.out.println("Next prime no. is "+ res);
    

    【讨论】:

      【解决方案4】:

      使用 eratosthenes 筛生成所有质数,直至达到您的极限。然后输入你的数字 n 并搜索如果 n> prime[i] , prime[i] 就是答案。

      【讨论】:

        【解决方案5】:

        你也可以使用这样的递归来做同样的事情:

        int nextPrime(int M) {
            if(!isPrime(M)) M = nextPrime(++M);
                return M;
        }
        boolean isPrime(int M) {
            for(int i = 2; i <= Math.sqrt(M); i++)
                if(M % i == 0) return false;
            return true;
        }
        

        【讨论】:

          【解决方案6】:

          我儿子用一种方法编写了自己的算法。 但它是用 python 编写的——你可以找到它here。

          在 Java 上看起来像:

          static long nextPrime(long number) {
              boolean prime = false;
              long n = number;
              while (!prime && n < number * 2) {
                  n++;
                  prime = true;
                  for (int i = 2; i < n; i++) {
                      if (n % i == 0) {
                          prime = false;
                          break;
                      }
                  }
              }
              return n;
          }
          

          【讨论】:

            【解决方案7】:

            这里我添加了一个求解算法。首先,while 循环在number + 1 到number * 2 的范围内抓取下一个要测试的数字。然后将数字发送到 isPrime 方法(使用 Java 8 streams),该方法迭代 stream 以查找没有其他因素的数字。

            private static int nextPrime(final int number) {
                int i = number + 1;
                while (!isPrime(i) && i < number * 2)
                    i++;
                return i;
            }
            
            private static boolean isPrime(final int number) {
                return number > 1 && IntStream.range(2, number).noneMatch(index -> number % index == 0);
            }
            

            【讨论】:

            【解决方案8】:

            老兄检查此代码。 while 循环中的 isPrime() 在增加当前素数/非素数后检查下一个素数。我确实使用了 long 数据类型(这就是我得到的作业)。

            if (isPrime(num)) {
                System.out.println("Current Prime number: " + num);
            } else {
                long a = getNextPrime(num);
                System.out.println("Next Prime:" + a);
            }
            
            public static long getNextPrime(long num) {
                long nextPrime = 0;
                while (true) {
                    num++;
                    boolean x = isPrime(num);
                    if (x) {
                        nextPrime = num;
                        break;
                    }
                }
            
                return nextPrime;
            }
            
            public static boolean isPrime(long num) {
                if (num == 0 || num == 1) {
                    return false;
                }
            
                for (long i = 2; i <= num / 2; ++i) {
                    if (num % i == 0) {
                        return false;
                    }
                } 
            
                return true;
            }
            

            【讨论】:

              【解决方案9】:

              这是查找下一个素数的实用方法。

              public void printFirstNPrimes(long n) {
                      Stream.iterate(2, i->nextPrime(i))
                      .limit(n).forEach(System.out::println);
              }
              
              public static boolean isPrime(long x) {
                  return Stream.iterate(2, i->i+1)
                              .limit((long)(Math.sqrt(x)))
                              .allMatch(n -> x % n != 0);
              }
              
              public static int nextPrime(int x) {
                  return isPrime(x+1)? x+1 : nextPrime(x+1);
              }
              

              【讨论】:

                【解决方案10】:

                所以,我正在阅读第一个答案并看到了一些潜在的升级。 我制作了它们并获得了非常显着的改进。

                原代码可以在22.32s内计算出200000个素数 稍作改动后,我设法在 11.41s 中执行了相同的操作,结果相同。

                请注意,我在笔记本电脑上执行代码 @2.50 GHz,在 IntelIJ 上运行。

                public static int nextPrime(int n) {
                
                    boolean isPrime;
                    n++;
                    while (true) {
                        int sqrt = (int) Math.sqrt(n);
                        isprime = true;
                        for (int i = 2; i <= sqrt; i++) {
                            if (n % i == 0) isPrime = false;
                        }
                        if (isPrime)
                            return n;
                        else {
                            n++;
                        }
                    }
                
                
                }
                

                希望你喜欢!

                【讨论】:

                  【解决方案11】:
                  public class ClosestPrimeNumber {
                  
                      static boolean isPrime(int n) {
                          for (int x = 2; x <= Math.sqrt(n); x++) {
                              if (n % x ==0) {
                                  return false;
                              }
                          }
                          return true;
                      }
                      static int next_forward = 0;
                      static int next_backward = 0;
                      static int next = 0;
                  
                      static int closestPrimeNumberForward(int n) {
                          if (isPrime(n)) {
                              next_forward = n;
                              return next_forward;
                          }else {
                              next_forward = n+1;
                              closestPrimeNumberForward(next_forward);
                          }
                          return next_forward;
                      }
                  
                      static int closestPrimeNumberBackward(int n) {
                          if (isPrime(n)) {
                              next_backward = n;
                              return next_backward;
                          }else {
                              next_backward = n-1;
                              closestPrimeNumberBackward(next_backward);
                          }
                          return next_backward;
                      }
                  
                      static int closestCompare(int forward, int backward, int num) {
                          return (Math.abs(num-backward) > Math.abs(num-forward) ) ? forward : backward; 
                      }
                  
                      public static void main(String[] args) {
                          int valor = 102;
                          System.out.println(closestCompare(closestPrimeNumberForward(valor), closestPrimeNumberBackward(valor), valor));
                      }
                  
                  }
                  

                  【讨论】:

                    【解决方案12】:
                    public int nextPrime(int input){
                      int counter;
                      while(true){
                        counter = 0;
                        for(int i = 1; i <= input; i ++){
                          if(input % i == 0)  counter++;
                        }
                        if(counter == 2)
                          return input;
                        else{
                          input++;
                          continue;
                        }
                      }
                    }
                    

                    这将返回 nextPrime 但不能说是最佳方式

                    • 这很简单,因为它执行一个无限循环,当 返回质数。
                    • 在while 中查找数字是否为素数
                    • 如果是素数,则返回该数字,如果不是,则增加输入并继续 while 循环

                    【讨论】:

                    • 嘿。你是否因为它被否决而删除并重新发布它?
                    • @lockcmpxchg8b 好吧,上一个是错误的答案,只是检查数字是否为素数
                    • 从另一个答案或第三方复制/粘贴。不酷。而且效率很低,顺便说一句。在相同的代码上查看我以前的 cmets。
                    • @nicomp 检查答案的时间并比较你是否认为我 copy/paste
                    • 好的,我明白了,但不,我没有复制粘贴,我在计算机科学的第二年学习中想出了代码
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2022-06-15
                    • 2022-06-22
                    • 1970-01-01
                    • 2014-04-19
                    • 2013-06-14
                    • 1970-01-01
                    相关资源
                    最近更新 更多