简体   繁体   English

计算素数的方法

[英]the method to calculate prime number

I am trying to figure out how this Java method calculates a prime number but something is confusing me. 我试图弄清楚这个Java方法是如何计算素数的,但是这让我感到困惑。

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

As you see in the second line in the for loop it shows divisor <= number /2 instead of divisor <= number . 如您在for循环的第二行中所看到的,它显示divisor <= number /2而不是divisor <= number Can anyone tell me the reason for that? 谁能告诉我原因呢?

First, if you put divisor <= number , you would get no prime numbers at all, because every number is divisible by itself. 首先,如果将divisor <= number放置,则根本不会得到素数,因为每个数本身都是可以整除的。 If the loop does not exit before divisor becomes number , you would get to 如果循环在divisor变为number之前没有退出,则可以转到

number % divisor == 0

condition, and return false . 条件,并返回false

Whoever wrote this code made an observation that you can stop as soon as you have reached half the number, because if you did not find divisors in the lower half of the interval (2..number/2) , there would be no divisors above half the number either, so you can declare the number prime without trying, unsuccessfully, the rest of the candidate divisors. 编写此代码的人都发现,一旦达到数值的一半,就可以立即停止,因为如果在间隔(2..number/2)的下半部分没有找到除数,则上面没有除数也可以是数字的一半,因此您可以声明数字为素数,而不会尝试其他候选除数失败。

However, this is not the best you can do: a stronger condition can be used - you could compare divisor to square root of number . 但是,这并不是您可以做的最好的事情:可以使用更强的条件-您可以将divisornumber平方根进行比较。 This works, because if you don't have a divisor that is less than or equal to the square root of number, there would be no divisors above the square root as well (it is a good idea to think why this is so). 之所以可行,是因为如果您没有小于或等于number的平方根的除数,那么在平方根的上方也不会有除数(考虑为什么这样做是个好主意)。

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

原因是任何数字都不能除以大于一半的除数并得到大于1的除数(当然,如果我们在说整数)。

Any number would not be divisible by a number more than its half. 任何数字都不能被其一半以上的数字整除。

For example, the last number 10 would be divisible is 5. 10 is not divisible with 6, 7, 8 or 9. 例如,最后一个数字10可以被5整除。10不能被6、7、8或9整除。

This is why it's good to eliminate the obvious mismatches to improve the performance of the algorithm. 这就是为什么最好消除明显的不匹配以提高算法的性能。

As others have noted, there are no factors of n greater than n/2. 正如其他人所指出的那样,不存在大于n / 2的n因子。 A better solution is comparing your iterating variable to the square root of n, as if there are no factors less than or equal to the square root, there can't be any greater than the square root (Note that it is more efficient to compare i*i <= n that i <= Math.sqrt(n)). 更好的解决方案是将迭代变量与n的平方根进行比较,就好像没有因子小于或等于平方根,也就不会有大于平方根的因子一样(请注意,比较起来效率更高i * i <= n表示我<= Math.sqrt(n))。

An even better approach is the AKS primality test. 更好的方法是AKS素数测试。 If the number is 2 or 3, then it obviously must be prime. 如果数字是2或3,则显然它必须是质数。 Otherwise, it can be rewritten in the form (6k+i) where i = -1, 0, 1, 2, 3, 4. Any (6k + 2) or (6k + 4) is divisible by 2, and any (6k + 3) is divisible by three, so the prime numbers must either take the form (6k - 1) or (6k + 1). 否则,可以将其重写为(6k + i)形式,其中i = -1、0、1、2、3、4。任何(6k + 2)或(6k + 4)都可以被2整除,而任何( 6k + 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;
  }
}

I used this as a part of my solution to the PrimeCounter problem in Sedgewick's Intro to Programming in Java (although this is in the first chapter before methods are introduced). 在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;
  }
}

It's using the fact that if one of the factors is greater than N/2 the other must be smaller than 2. 它利用以下事实:如果其中一个因子大于N / 2,另一个必须小于2。

In fact a massive (asymptotic) gain can be obtained by using the square-root. 实际上,可以通过使用平方根获得大量(渐近)增益。

That's because if one factor is greater than the square root the other is less. 这是因为,如果一个因素大于平方根,另一个因素则小于。

Sorry Sebri Zouhaier. 抱歉,Sebri Zouhaier。 I'm changing allegiance. 我正在改变效忠。 The +1 isn't necessary so the best answer is below. +1不是必需的,因此最佳答案如下。 I'm sorry to change sides for such a tiny improvement! 抱歉为了这么小的改进而改变立场!

A number N cannot have any divisors D that are > N /2 and < N . 数字N不能有大于N / 2和< N的除数D。 To see this, note that if D is a divisor of N , then it must equal N / D 2 for some D 2 . 看到这一点,请注意,如果dN的约数,则它必须等于N / d 2为一些d 2。 So the divisors of N are those values of this sequence that are integers: N , N /2, N /3, ... This is a descending sequence. 因此, N的除数是该序列的那些值,它们是整数: NN / 2, N / 3,...。这是一个降序序列。 It should be obvious that there can't be any divisors between N and N /2. 很明显, NN / 2之间不能有除数。

In fact, it's common for programs that check for primality to stop at sqrt( N ) instead of N /2. 实际上,检查素数的程序通常以sqrt( N )而不是N / 2停止。 The reason is this: Suppose there's a divisor D such that D > sqrt( N ). 原因是:假设存在一个除数D ,使得D > sqrt( N )。 Then N / D = D 2 also must be a divisor of N . 那么N / D = D 2也必须是N的除数。 And it must be the case that D 2 < sqrt( N ), because if both D and D 2 were > sqrt( N ), then D * D 2 would have to be > N , which is wrong because D * D 2 = N . 而且一定是D 2 <sqrt( N )的情况,因为如果DD 2都> sqrt( N ),那么D * D 2一定要> N ,这是错误的,因为D * D 2 = N. This means that there is no need to check possible divisors D > sqrt( N ); 这意味着无需检查可能的除数D > sqrt( N ); if such a divisor existed, we already would have found D 2 earlier in the loop and proven that N was not prime. 如果存在这样的除数,那么我们早在循环中就已经找到了D 2并证明N不是素数。

One small caveat to some of the above answers is that 0 and 1 are not prime numbers. 上述某些答案的一个小警告是0和1不是质数。 You could account for this (for positive integers) with an implementation such as 您可以使用以下实现来解决此问题(对于正整数)

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;

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM