计算素数的方法

时间:2014-11-18 16:20:13

标签: java math primes

我试图弄清楚这个Java方法如何计算素数,但有些事让我感到困惑。

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

正如您在for循环的第二行中看到的那样,它显示divisor <= number /2而不是divisor <= number。谁能告诉我原因呢?

8 个答案:

答案 0 :(得分:7)

首先,如果你放divisor <= number,你就不会得到素数,因为每个数字都可以自行整除。如果循环在divisor变为number之前没有退出,您将进入

number % divisor == 0

条件,并返回false

无论是谁写了这段代码,都会发现你可以在达到一半的数量后立即停止,因为如果你在(2..number/2)的下半部分没有找到除数,那么上面就没有除数这个数字的一​​半,所以你可以声明数字素数,而不会尝试其他候选除数,但不成功。

但是,这不是你能做的最好的事情:可以使用更强的条件 - 你可以将divisornumber的平方根进行比较。这是有效的,因为如果你没有一个小于或等于数字平方根的除数,那么平方根上面也不会有除数(考虑为什么这样做是个好主意) )。

int stop = Math.sqrt(number);
for(int divisor = 2; divisor <= stop ; divisor++) {
    ...
}

答案 1 :(得分:3)

原因是任何数字都不能除以任何大于它的半数的除数,并且给出多于1(如果我们说的是整数,当然)。

答案 2 :(得分:2)

任何数字都不能被一半以上的数字整除。

例如,最后一个数字10可以被整除为5. 10不能被6,7,8或9整除。

这就是为什么消除明显的不匹配以提高算法性能的原因。

答案 3 :(得分:1)

正如其他人所指出的,没有n大于n / 2的因素。一个更好的解决方案是将迭代变量与n的平方根进行比较,就好像没有小于或等于平方根的因子一样,不能有任何大于平方根(注意它比较有效率) i * i&lt; = n,我&lt; = Math.sqrt(n))。

更好的方法是AKS素性测试。如果数字是2或3,那么它显然必须是素数。否则,它可以以(6k + i)形式重写,其中i = -1,0,1,2,3,4。任何(6k + 2)或(6k + 4)可被2整除,并且任何( 6k + 3)可被3整除,因此素数必须采用(6k - 1)或(6k + 1)形式。

public static boolean isPrime(long n) { 
    /* This code uses the AKS primality test
     * http://en.wikipedia.org/wiki/AKS_primality_test
     */
    if (n <= 3) return n > 1;
    if (n % 2 == 0 || n % 3 == 0) return false;
    for (int i = 5; i*i <=n; i+=6) {
      if (n % i == 0 || n % (i+2) == 0) return false; 
    }
    return true;
  }
}

我在Sedgewick的Java编程简介(虽然这是在引入方法之前的第一章)中将此作为我PrimeCounter问题解决方案的一部分。

public class PrimeCounter {
  public static void main(String[] args) {
    long n = 10000000;
    long count = 0;
    for (long i = 0; i <= n; i++) {
      if (isPrime(i)) count++;
    }
    System.out.println("The number of primes less than "
                         + n + " is " + count);
  }


  public static boolean isPrime(long n) { 
    /* This code uses the AKS primality test
     * http://en.wikipedia.org/wiki/AKS_primality_test
     */
    if (n <= 3) return n > 1;
    if (n % 2 == 0 || n % 3 == 0) return false;
    for (int i = 5; i*i <=n; i+=6) {
      if (n % i == 0 || n % (i+2) == 0) return false; 
    }
    return true;
  }
}

答案 4 :(得分:0)

它使用的事实是,如果其中一个因子大于N / 2,则另一个因子必须小于2.

事实上,通过使用平方根可以获得大量(渐近)增益。

那是因为如果一个因子大于平方根,另一个因子就更少了。

抱歉Sebri Zouhaier。我正在改变效忠。 +1不是必需的,所以最佳答案如下。 我很抱歉为了这么微小的改进而改变立场!

答案 5 :(得分:0)

数字 N 不能有任何除数 D <> N / 2和&lt; 名词的。要看到这一点,请注意,如果 D N 的除数,那么它必须等于 N / D < sub> 2 表示某些 D 2 。所以 N 的除数是这个序列的整数值: N N / 2, N / 3,......这是一个降序。很明显, N N / 2之间不存在任何除数。

事实上,检查primality的程序在sqrt( N )而不是 N / 2处停止是很常见的。原因是:假设存在除数 D ,使得 D &gt; SQRT(名词的)。那么 N / D = D 2 也必须是 N 的除数。并且必须是 D 2 &lt; sqrt( N ),因为如果 D D 2 都是&gt; sqrt( N ),然后 D * D 2 必须是&gt; N ,这是错误的,因为 D * D 2 = N 。这意味着无需检查可能的除数 D &gt; SQRT(名词的);如果存在这样的除数,我们已经在循环的早期找到 D 2 并证明 N 不是素数。

答案 6 :(得分:0)

对上述一些答案的一个小警告是0和1不是素数。您可以使用诸如

之类的实现来解释这个(对于正整数)
public static boolean isPrime(int number){
    if (number == 0 || number == 1) 
        return false;
    else
    {
        int stop = (int) Math.sqrt(number);
        for (int divisor = 2; divisor <= stop ; divisor++) 
        {
               if (number % divisor ==0)
                    return false;

        }
            return true;

        }
    }

答案 7 :(得分:-1)

public static Boolean isPrime(int num){ //method signature. returns Boolean, true if number isPrime, false if not
if(num==2){ //for case num=2, function returns true. detailed explanation underneath
  return(true);
}
for(int i=2;i<=(int)Math.sqrt(num)+1;i++){ //loops through 2 to sqrt(num). All you need to check- efficient
  if(num%i==0){ //if a divisor is found, its not prime. returns false
    return(false);
  }
}
return(true); //if all cases don't divide num, it is prime.

}


    // Returns true iff n is prime.  First checks if n is even, handling the
// cases of n=2 (prime) or n is even > 2 (not prime).  Then checks if any
// odd #'s between 3 and sqrt(n), inclusive, are divisors of n, returning
// false if any are.
public static boolean isPrime(int n) {
    if (n < 2) return false;
    if (n % 2 == 0)
        // n is an even, so return true iff n is exactly 2
        return (n == 2);
    for (int i=3; i*i<=n; i+=2)
        if (n % i == 0)
            // i divides evenly into n, so n is not prime
            return false;
    return true;
}