How do I generate Primes Using 6*k +- 1 rule

前端 未结 7 1441
离开以前
离开以前 2021-02-04 02:07

We know that all primes above 3 can be generated using:

6 * k + 1
6 * k - 1

However we all numbers generated from the above formulas are not pr

7条回答
  •  逝去的感伤
    2021-02-04 02:39

    Probably the most suitable standard datastructure for Sieve of Eratosthenes is the BitSet. Here's my solution:

    static BitSet genPrimes(int n) {
        BitSet primes = new BitSet(n);
        primes.set(2); // add 2 explicitly
        primes.set(3); // add 3 explicitly
        for (int i = 6; i <= n ; i += 6) { // step by 6 instead of multiplication
            primes.set(i - 1);
            primes.set(i + 1);
        }
        int max = (int) Math.sqrt(n); // don't need to filter multiples of primes bigger than max
    
        // this for loop enumerates all set bits starting from 5 till the max
        // sieving 2 and 3 is meaningless: n*6+1 and n*6-1 are never divisible by 2 or 3
        for (int i = primes.nextSetBit(5); i >= 0 && i <= max; i = primes.nextSetBit(i+1)) {
            // The actual sieve algorithm like in your code
            for(int j = i * i; j <= n; j += i)
                primes.clear(j);
        }
        return primes;
    }
    

    Usage:

    BitSet primes = genPrimes(1000); // generate primes up to 1000
    System.out.println(primes.cardinality()); // print number of primes
    // print all primes like {2, 3, 5, ...}
    System.out.println(primes);
    // print all primes one per line
    for(int prime = primes.nextSetBit(0); prime >= 0; prime = primes.nextSetBit(prime+1))
        System.out.println(prime);
    // print all primes one per line using java 8:
    primes.stream().forEach(System.out::println);
    

    The boolean-based version may work faster for small n values, but if you need, for example, a million of prime numbers, BitSet will outperform it in several times and actually works correctly. Here's lame benchmark:

    public static void main(String... args) {
        long start = System.nanoTime();
        BitSet res = genPrimes(10000000);
        long diff = System.nanoTime() - start;
        System.out.println(res.cardinality() + "\tBitSet Seconds: " + diff / 1e9);
    
        start = System.nanoTime();
        List result = generatePrimesBoolean(10000000); // from durron597 answer
        diff = System.nanoTime() - start;
        System.out.println(result.size() + "\tBoolean Seconds: " + diff / 1e9);
    }
    

    Output:

    664579  BitSet Seconds: 0.065987717
    664116  Boolean Seconds: 0.167620323
    

    664579 is the correct number of primes below 10000000.

提交回复
热议问题