繁体   English   中英

数素数直到N

[英]Count prime number till N

这段代码可以很好地计算素数直到 n。 问题是当 n 值大到 1000000 或更多时,执行和打印输出需要很长时间(超过 30 秒)。 我想解决这个问题。 任何帮助都会很棒。 下面是代码:

public class PrimeNotillN {

        public static void main(String[] args) {

            int n = 1000;
            int count = 0;

            for (int i = 2; i < n; i++) {
                boolean res = checkprime(i);
                if (res == true)
                    count++;
            }
            System.out.println("total prime number till " + n + " is " + count);
        }

        private static boolean checkprime(int n) {
            if (n == 1)
                return false;
            else {
                for (int i = 2; i <= n / 2; i++) {
                    if (n % i == 0) {

                        return false;
                    }
                }

                return true;
            }
        }
    }

做最简单的变化是结束for在循环checkprime后, i已经达到的平方根n 原因是如果你发现一个因子大于n平方根,那就意味着有一个因子小于应该已经找到的n平方根。

for (int i = 2; i <= Math.sqrt(n); i++) {

此外,如果您需要更高的速度,将所有素数打印到最大限度的最佳算法是EratosthenesSieve 这涉及到取代你拥有的东西。 你需要一个数组,你可以在其中标记哪些数字是复合数。 从2开始,您将所有2的倍数标记为复合。 在数组中移动,如果您找到一个未标记为复合的数字,则它是素数,您可以打印它。 对于您遇到的每个素数,您将所有素数的倍数标记为复合。

除了2之外,素数从来都不是。 Primes只能被1和iteslef整除。

你也可以查看它的sqrt。 如果你什么都没发现那么它就是一个素数。

        public bool IsPrime(double num)
    {
        bool isprime = true;
        double limit = Math.Sqrt(num);

        if (num % 2 == 0)
            return num == 2;

        if (num == 3 || num == 5 || num == 7)
            return true;

        for (int i = 3; i < limit; i++)
            if (num % 1 == 0)
                return false;

        return isprime;
    }

Eratosthenes 筛法是一种非常著名且高效的算法,可以生成大约 1-1000 万个小素数。 这是一个古老的算法,由一位名叫 Eratosthenes 的希腊数学家给出。

 public class CountPrimes {

  public static void main(String[] args) {
    System.out.println(countPrimes(1000000));
  }

  public static int countPrimes(int n) {
    boolean[] primes = new boolean[n +1];

    for(int i = 0 ; i <= n ; i++) {
        primes[i] = true;
    }

    primes[0] = false;
    primes[1] = false;

    for(int i = 2 ; i * i <= n ; i++) {
        if(primes[i]) {
            for(int j = i ; i * j <= n ; j++) {
                primes[j * i ] = false;
            }
        }   
    }

    int primeCounts = 0;
    for(int i = 2 ; i <= n ; i++) {
        if(primes[i]) {
            primeCounts++;
        }
    }

    return primeCounts;
  }

}

您可以将找到的素数存储到列表中,并仅对它们进行进一步检查(Sieve of Eratosphenes):

import java.util.ArrayList;
import java.util.List;

public class PrimeNotillN {
    public static void main(String[] args) {
        int n = 1000000;
        int count = 0;
        List<Integer> primes = new ArrayList<>();

        for (int i = 2; i < n; i++) {
            boolean res = checkprime(primes, i);
            if (res) {
                count++;
                primes.add(i);
            }
        }
        System.out.println("total prime number till " + n + " is " + count);
    }

    private static boolean checkprime(List<Integer> primes, int n) {
        int fence = (int) Math.sqrt(n);
        for (int prime : primes) {
            if (n % prime == 0) {
                return false;
            }
            if (prime >= fence)
                break;
        }

        return true;
    }
}

使用eratoshtenes方法的筛子并保持所有素数的缓存

    public int countPrimes(int n) {
    if(n==0){
        return 0;
    }else{
        boolean[] isPrime=new boolean[n];
        for(int i=2;i<n;i++){
            isPrime[i]=true;
        }

        for(int i=2;i*i<n;i++){
           if(!isPrime[i]){
               continue;
           }
            for(int j=i*i;j<n;j+=i){
                isPrime[j]=false;
            }
        }

        int counter=0;
        for(int i=2;i<n;i++){
            if(isPrime[i]){
                counter++;
            }
        }

        return counter;

    }
}

暂无
暂无

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

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