寻找质数的有效算法的实现差异与数学证明

时间:2015-08-23 09:42:34

标签: java algorithm

当我从梁的Java编程书的介绍中学习时,我陷入了困境。问题是要有效地找到素数。

为了找出n是否为素数,我们必须检查n是否可被数字2,3,4,...,sqrt(n)整除。

我们可以通过检查n是否可以被数字2,3,4,...,floor(sqrt(n))整除来使这个算法更有效。

例如,36到48之间的数字,它们的(int)(Math.sqrt(数字))是6.但是,根据以下程序,对于数字= 40,squareRoot是7,而不是6.即,< strong>根据数学证明,我们检查40是否是素数,通过检查40可以被2,3,4,5,6整除。 根据下面的程序,我们检查40是否是素数,通过检查40可以被2,3,4,5,6,7整除。这个矛盾。我不明白。请帮忙。

以下是实现此问题的算法:

import java.util.Scanner;

public class EfficientPrimeNumbers {
  public static void main(String[] args) {
    Scanner input = new Scanner(System.in);
    System.out.print("Find all prime numbers <= n, enter n: ");
    int n = input.nextInt();

    // A list to hold prime numbers
    java.util.List<Integer> list = 
      new java.util.ArrayList<Integer>(); 

    final int NUMBER_PER_LINE = 10; // Display 10 per line
    int count = 0; // Count the number of prime numbers
    int number = 2; // A number to be tested for primeness
    int squareRoot = 1; // Check whether number <= squareRoot

    System.out.println("The prime numbers are \n");

    // Repeatedly find prime numbers
    while (number <= n) {
      // Assume the number is prime
      boolean isPrime = true; // Is the current number prime?

      if (squareRoot * squareRoot < number) squareRoot++;
      // For numbers between 36 and 48, squareRoot is 7 which contradicts with the matematical proof.!!!

      // ClosestPair if number is prime
      for (int k = 0; k < list.size() 
                        && list.get(k) <= squareRoot; k++) {
        if (number % list.get(k) == 0) { // If true, not prime
          isPrime = false; // Set isPrime to false          
          break; // Exit the for loop
        }
      }

      // Print the prime number and increase the count
      if (isPrime) {
        count++; // Increase the count
        list.add(number); // Add a new prime to the list
        if (count % NUMBER_PER_LINE == 0) {
          // Print the number and advance to the new line
          System.out.println(number);
        }
        else
          System.out.print(number + " ");
      }

      // Check if the next number is prime
      number++;
    }

    System.out.println("\n" + count + 
      " prime(s) less than or equal to " + n);
  }
}

1 个答案:

答案 0 :(得分:0)

该程序仅通过素数检查可分性低于或等于sqrt(number) + 1。检测到素数后,它会添加到您的list对象中:

if (isPrime) {
    count++; // Increase the count
    list.add(number); // Add a new prime to the list

您可以在此处按照此列表中的数字检查可分性:

for (int k = 0; k < list.size() && list.get(k) <= squareRoot; k++) {
    if (number % list.get(k) == 0) { // If true, not prime

因此,对于3648之间的数字,它会检查2, 3, 5, 7,这实际上比2, 3, 4, 5, 6更好。渐渐地,它们仍然是相同的,但在实践中,你通过仅检查对素数的可分性来节省一些工作。

实际上,由于您描述的原因,您可以保存操作并将<=中的list.get(k) <= squareRoot更改为<。然后,对于736之间的数字,它甚至不会对48感到烦恼,而且它将更接近您所拥有的理论。