【问题标题】:Calculate nth prime.. in java?在java中计算第n个素数..?
【发布时间】:2011-01-12 17:06:07
【问题描述】:

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

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

【问题讨论】:

标签: java primes


【解决方案1】:

要获得第 n 个素数,只需使用 array[n-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 或使用其他方法(即其他语言和/或库)

    干杯!

    【讨论】:

    • 我认为您的意思是 primes.get(i) 而不是 primes[i]
    • 好吧,首先,我什至不确定你的程序应该做什么......它从标准输入输入一个 int,然后创建一个包含 1000 个元素的数组并用值填充它从 2 到 1000(跳过索引 0 和 1),然后将数组中的元素(包括索引 0 和 1...,它们都是 == 0)复制到 ArrayList 中,删除前两个元素...对其进行排序( ??) 然后再次循环遍历每个元素并打印任何为素数的元素...为什么是第一个输入?您想从该输入(第 n 个)打印素数吗?如果我必须更改您的代码,我将不得不全部重写(抱歉诚实)
    • 我正在打印一个程序中从 2 到 1000 的数字列表并将其存储为一个数组。然后我想使用每个循环将这些数字添加到列表中,然后我检查每个数字是否为素数..然后我想将所有素数#添加到列表中并在特定索引上获取素数..让说 whts da first prime # 它的 2 .. 所以在列表的索引 1 应该有 2 并且当我插入 n 的值为 1 时程序应该 2 作为它的第一个素数 #... 你可以继续并更改代码..
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2012-03-26
      • 1970-01-01
      • 1970-01-01
      • 2013-02-23
      • 1970-01-01
      • 1970-01-01
      • 2012-02-08
      • 2011-01-29
      • 2019-01-15
      相关资源
      最近更新 更多