在java中计算nth prime ..

时间:2011-01-12 17:06:07

标签: java primes

我打印出程序中的素数列表并将其存储为数组。然后我想得到特定索引上的素数而不是总列表..

import java.util.*;

public class Gauss {
    static int n;
    static int[] array;

    public static void Input() {
        Scanner input = new Scanner(System.in);
        System.out.println("Enter N: ");
        n = input.nextInt();
    }

    public static boolean isPrime(int num) {
        boolean prime = true;
        int limit = (int) Math.sqrt(num);

        for (int i = 2; i <= limit; i++) {
            if (num % i == 0) {
                prime = false;
                break;
            }
        }

        return prime;
    }

    public static void Calc() {
        Input();
        array = new int[1000];

        for (int i = 2; i < array.length; i++) {
            array[i] = i;
        }

        ArrayList<Integer> list = new ArrayList<Integer>(array.length);

        for (int c : array) {
            list.add(c);
        }

        list.remove(0);
        list.remove(0);

        Collections.sort(list);

        for (int k : list) {
            if (isPrime(k)) {
                System.out.println(k);
            }
        }
    }

    public static void main(String[] args) {
        Calc();
    }
}

3 个答案:

答案 0 :(得分:4)

要获得第n个素数,只需使用数组[n-1]

答案 1 :(得分:2)

您可能会发现this answer对类似问题很有用。

你可以用

获得第n个素数
List<Integer> primes = findPrimes(0, n);
System.out.println( primes.get(i) );

** 编辑 **

这是我提出的整体测试程序(自上次发布的答案以来修改过),并进行了基准测试。我知道有更快的实现,并且仍然可以进行一些优化,但是这里有一些生成素数的算法:

public class PrimeTests {

    public static void main(String... args) {
        AbstractPrimeGenerator[] generators = new AbstractPrimeGenerator[] {
            new DefaultPrimeGenerator(), 
            new AtkinSievePrimeGenerator(),
            new SundaramSievePrimeGenerator() 
        };
        int[] primes;
        int[] old_primes = null;
        double[] testAvg = new double[generators.length];

        long ts, te;
        double time;
        DecimalFormat df = new DecimalFormat("0.0######################");

        int max = 10000000;
        int testCountLoop = 10;

        int it = 0, ti;
        while (it++ < testCountLoop) {
            ti = 0;
            for (AbstractPrimeGenerator g : generators) {
                ti++;

                System.out.println(it + "." + ti + ". Calculating " + max
                        + " primes numbers from " + g.getName() + "...");
                ts = System.nanoTime();
                primes = g.findPrimes(max);
                te = System.nanoTime();
                time = (te - ts) * Math.pow(10, -9) * 1000;
                df.setRoundingMode(RoundingMode.HALF_UP);

                testAvg[ti - 1] += time;

                System.out.println("Found " + primes.length
                        + " prime numbers (in " + time + " ms, "
                        + df.format(time / primes.length) + " ms per prime)");
                // for (int prime : primes) {
                // System.out.print(prime + "... ");
                // }
                // System.out.println();

                if (old_primes != null) {
                    System.out.print("Validating primes.... ");
                    if (primes.length == old_primes.length) {
                        for (int i = 0; i < primes.length; i++) {
                            if (primes[i] != old_primes[i]) {
                                System.out.println("Prime number does not match : " + primes[i] + " != " + old_primes[i] + " at index " + i);
                                System.exit(-1);
                            }
                        }
                    } else {
                        System.out.println("ERROR!! No match in prime results");
                        System.exit(-1);
                    }
                    System.out.println("Ok!");
                }
                old_primes = primes;
            }

            System.out.println("................");
        }

        System.out.println("Results:");
        ti = 0;
        for (AbstractPrimeGenerator g : generators) {
            time = (testAvg[ti++] / testCountLoop);

            System.out.println(ti + ". Average time finding " + max
                    + " primes numbers from " + g.getName() + " = " + time
                    + " ms or " + df.format(time / old_primes.length)
                    + " ms per prime");
        }

        System.out.println("Done!");
    }

    /**
     * Base class for a prime number generator
     */
    static abstract public class AbstractPrimeGenerator {
        /**
         * The name of the generator
         * 
         * @return String
         */
        abstract public String getName();

        /**
         * Returns all the prime numbers where (2 <= p <= max)
         * 
         * @param max
         *            int the maximum value to test for a prime
         * @return int[] an array of prime numbers
         */
        abstract public int[] findPrimes(int max);
    }

    /**
     * Default naive prime number generator. Based on the assumption that any
     * prime n is not divisible by any other prime m < n (or more precisely m <=
     * sqrt(n))
     */
    static public class DefaultPrimeGenerator extends AbstractPrimeGenerator {
        @Override
        public String getName() {
            return "Default generator";
        }

        @Override
        public int[] findPrimes(int max) {
            int[] primes = new int[max];
            int found = 0;
            boolean isPrime;

            // initial prime
            if (max > 2) {
                primes[found++] = 2;

                for (int x = 3; x <= max; x += 2) {
                    isPrime = true; // prove it's not prime
                    for (int i = 0; i < found; i++) {
                        isPrime = x % primes[i] != 0; // x is not prime if it is
                                                        // divisible by p[i]
                        if (!isPrime || primes[i] * primes[i] > x) {
                            break;
                        }
                    }
                    if (isPrime) {
                        primes[found++] = x; // add x to our prime numbers
                    }
                }
            }

            return Arrays.copyOf(primes, found);
        }
    }

    /**
     * Sieve of Atkin prime number generator Implementation following the Sieve
     * of Atkin to generate prime numbers
     * 
     * @see http://en.wikipedia.org/wiki/Sieve_of_Atkin
     */
    static public class AtkinSievePrimeGenerator extends AbstractPrimeGenerator {
        @Override
        public String getName() {
            return "Sieve of Atkin generator";
        }

        @Override
        public int[] findPrimes(int max) {
            boolean[] isPrime = new boolean[max + 1];
            double sqrt = Math.sqrt(max);

            for (int x = 1; x <= sqrt; x++) {
                for (int y = 1; y <= sqrt; y++) {
                    int n = 4 * x * x + y * y;
                    if (n <= max && (n % 12 == 1 || n % 12 == 5)) {
                        isPrime[n] = !isPrime[n];
                    }

                    n = 3 * x * x + y * y;
                    if (n <= max && (n % 12 == 7)) {
                        isPrime[n] = !isPrime[n];
                    }

                    n = 3 * x * x - y * y;
                    if (x > y && (n <= max) && (n % 12 == 11)) {
                        isPrime[n] = !isPrime[n];
                    }
                }
            }

            for (int n = 5; n <= sqrt; n++) {
                if (isPrime[n]) {
                    int s = n * n;
                    for (int k = s; k <= max; k += s) {
                        isPrime[k] = false;
                    }
                }
            }

            int[] primes = new int[max];
            int found = 0;
            if (max > 2) {
                primes[found++] = 2;
            }
            if (max > 3) {
                primes[found++] = 3;
            }
            for (int n = 5; n <= max; n += 2) {
                if (isPrime[n]) {
                    primes[found++] = n;
                }
            }

            return Arrays.copyOf(primes, found);
        }
    }

    /**
     * Sieve of Sundaram prime number generator Implementation following the
     * Sieve of Sundaram to generate prime numbers
     * 
     * @see http://en.wikipedia.org/wiki/Sieve_of_Sundaram
     */
    static public class SundaramSievePrimeGenerator extends
            AbstractPrimeGenerator {
        @Override
        public String getName() {
            return "Sieve of Sundaram generator";
        }

        @Override
        public int[] findPrimes(int max) {
            int n = max / 2;
            boolean[] isPrime = new boolean[max];

            Arrays.fill(isPrime, true);

            for (int i = 1; i < n; i++) {
                for (int j = i; j <= (n - i) / (2 * i + 1); j++) {
                    isPrime[i + j + 2 * i * j] = false;
                }
            }

            int[] primes = new int[max];
            int found = 0;
            if (max > 2) {
                primes[found++] = 2;
            }
            for (int i = 1; i < n; i++) {
                if (isPrime[i]) {
                    primes[found++] = i * 2 + 1;
                }
            }

            return Arrays.copyOf(primes, found);
        }
    }

}

在我的机器上,结果给出:

Results:
1. Average time finding 10000000 primes numbers from Default generator = 1108.7848961000002 ms or 0.0016684019448402676 ms per prime
2. Average time finding 10000000 primes numbers from Sieve of Atkin generator = 199.8792727 ms or 0.0003007607413114167 ms per prime
3. Average time finding 10000000 primes numbers from Sieve of Sundaram generator = 132.6467922 ms or 0.00019959522073372766 ms per prime

使用上面一个类的方法(你不需要实际的基类和所有,只有实际的方法),你可以这样做:

public class PrimeTest2 {

    static public int[] findPrimes(int max) {
        int[] primes = new int[max];
        int found = 0;
        boolean isPrime;

        // initial prime
        if (max > 2) {
            primes[found++] = 2;

            for (int x = 3; x <= max; x += 2) {
                isPrime = true; // prove it's not prime
                for (int i = 0; i < found; i++) {
                    isPrime = x % primes[i] != 0; // x is not prime if it is
                                                    // divisible by p[i]
                    if (!isPrime || primes[i] * primes[i] > x) {
                        break;
                    }
                }
                if (isPrime) {
                        primes[found++] = x; // add x to our prime numbers
                }
            }
        }

        return Arrays.copyOf(primes, found);
    }

    public static void main(String... args) {

        Scanner input = new Scanner(System.in);
        int MAX_N = Integer.MAX_VALUE / 100;
        int n = 0;
        while (n <= 0 || n >= MAX_N) {
            System.out.print("Enter N: ");
            n = input.nextInt();
            if (n <= 0) {
                System.out.println("n must be greater than 0");
            }
            if (n >= MAX_N) {
                System.out.println("n must be smaller than " + MAX_N);
            }
        }
        int max = n * 100; // just find enough prime numbers....

        int[] primes = findPrimes(max);
        System.out.println("Number of prime numbers found from " + 0 + " to "
                + max + " = " + primes.length);
        System.out.println("The " + n
                + (n == 1 ? "st" : n == 2 ? "nd" : n == 3 ? "rd" : "th")
                + " prime number is : " + primes[n - 1]);

    }
}

将输出(例如):

Enter N: 10000
Number of prime numbers found from 0 to 1000000 = 78498
The 10000th prime number is : 104729

有了这个,你就可以说关于找到第n个素数了。对于较大的数字(超出int),您必须修改“默认生成器”的未优化方法以接受long或使用其他方法(即其他语言和/或库)

干杯!

答案 2 :(得分:0)

您拥有的代码几乎是可行的方法,Roflcopter选择数字的答案是正确的,但您可以做一个可以显着提高性能的优化。不是除以小于或等于平方根的所有数字,而是仅除以小于或等于平方根的PRIMES。任何不能被你发现的任何素数整除的数字也不能被任何相同的组合整除,这是非主要数字的定义(具有除1 * N之外的素数因子分解)