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

前端 未结 7 1409
离开以前
离开以前 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:52

    You don't need to add all possible candidates to the array. You can create a Set to store all non primes.

    Also you can start checking at k * k, rather than 2 * k

      public void primesTo1000() {
        Set notPrimes = new HashSet<>();
        ArrayList primes = new ArrayList<>();
        primes.add(2);//explicitly add
        primes.add(3);//2 and 3
    
        for (int i = 1; i < (1000 / 6); i++) {
          handlePossiblePrime(6 * i - 1, primes, notPrimes);
          handlePossiblePrime(6 * i + 1, primes, notPrimes);
        }
        System.out.println(primes);
      }
    
      public void handlePossiblePrime(
          int k, List primes, Set notPrimes) {
        if (!notPrimes.contains(k)) {
          primes.add(k);
          for (int j = k * k; j <= 1000; j += k) {
            notPrimes.add(j);
          }
        }
      }
    

    untested code, check corners


    Here is a bit packing version of the sieve as suggested in the answer referenced by @Will Ness. Rather than return the nth prime, this version returns a list of primes to n:

    public List primesTo(int n) {
      List primes = new ArrayList<>();
      if (n > 1) {
        int limit = (n - 3) >> 1;
        int[] sieve = new int[(limit >> 5) + 1];
        for (int i = 0; i <= (int) (Math.sqrt(n) - 3) >> 1; i++)
          if ((sieve[i >> 5] & (1 << (i & 31))) == 0) {
            int p = i + i + 3;
            for (int j = (p * p - 3) >> 1; j <= limit; j += p)
              sieve[j >> 5] |= 1 << (j & 31);
          }
        primes.add(2);
        for (int i = 0; i <= limit; i++)
          if ((sieve[i >> 5] & (1 << (i & 31))) == 0)
            primes.add(i + i + 3);
      }
      return primes;
    }
    

    There seems to be a bug in your updated code that uses a boolean array (it is not returning all the primes).

    public static List booleanSieve(int n) {
      boolean[] primes = new boolean[n + 5];
      for (int i = 0; i <= n; i++)
        primes[i] = false;
      primes[2] = primes[3] = true;
      for (int i = 1; i <= n / 6; i++) {
        int prod6k = 6 * i;
        primes[prod6k + 1] = true;
        primes[prod6k - 1] = true;
      }
      for (int i = 0; i <= n; i++) {
        if (primes[i]) {
          int k = i;
          for (int j = k * k; j <= n && j > 0; j += k) {
            primes[j] = false;
          }
        }
      }
    
      List primesList = new ArrayList<>();
      for (int i = 0; i <= n; i++)
        if (primes[i])
          primesList.add(i);
    
      return primesList;
    }
    
    public static List bitPacking(int n) {
      List primes = new ArrayList<>();
      if (n > 1) {
        int limit = (n - 3) >> 1;
        int[] sieve = new int[(limit >> 5) + 1];
        for (int i = 0; i <= (int) (Math.sqrt(n) - 3) >> 1; i++)
          if ((sieve[i >> 5] & (1 << (i & 31))) == 0) {
            int p = i + i + 3;
            for (int j = (p * p - 3) >> 1; j <= limit; j += p)
              sieve[j >> 5] |= 1 << (j & 31);
          }
        primes.add(2);
        for (int i = 0; i <= limit; i++)
          if ((sieve[i >> 5] & (1 << (i & 31))) == 0)
            primes.add(i + i + 3);
      }
      return primes;
    }
    
    public static void main(String... args) {
      Executor executor = Executors.newSingleThreadExecutor();
      executor.execute(() -> {
        for (int i = 0; i < 10; i++) {
          int n = (int) Math.pow(10, i);
          Stopwatch timer = Stopwatch.createUnstarted();
          timer.start();
          List result = booleanSieve(n);
          timer.stop();
          System.out.println(result.size() + "\tBoolean: " + timer);
        }
    
        for (int i = 0; i < 10; i++) {
          int n = (int) Math.pow(10, i);
          Stopwatch timer = Stopwatch.createUnstarted();
          timer.start();
          List result = bitPacking(n);
          timer.stop();
          System.out.println(result.size() + "\tBitPacking: " + timer);
        }
      });
    }
    

    0   Boolean: 38.51 μs
    4   Boolean: 45.77 μs
    25  Boolean: 31.56 μs
    168 Boolean: 227.1 μs
    1229    Boolean: 1.395 ms
    9592    Boolean: 4.289 ms
    78491   Boolean: 25.96 ms
    664116  Boolean: 133.5 ms
    5717622 Boolean: 3.216 s
    46707218    Boolean: 32.18 s
    0   BitPacking: 117.0 μs
    4   BitPacking: 11.25 μs
    25  BitPacking: 11.53 μs
    168 BitPacking: 70.03 μs
    1229    BitPacking: 471.8 μs
    9592    BitPacking: 3.701 ms
    78498   BitPacking: 9.651 ms
    664579  BitPacking: 43.43 ms
    5761455 BitPacking: 1.483 s
    50847534    BitPacking: 17.71 s
    

提交回复
热议问题