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

9

21

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 prime.

For Example:    
6 * 6 - 1 = 35 which is clearly divisible by 5.

To Eliminate such conditions, I used a Sieve Method and removing the numbers which are factors of the numbers generated from the above formula.

Using the facts:

A number is said to be prime if it has no prime factors.

  1. As we can generate all the prime numbers using the above formulas.
  2. If we can remove all the multiples of the above numbers we are left with only prime numbers.

To generate primes below 1000.

ArrayList<Integer> primes = new ArrayList<>();
primes.add(2);//explicitly add
primes.add(3);//2 and 3
int n = 1000;
for (int i = 1; i <= (n / 6) ; i++) {
//get all the numbers which can be generated by the formula
    int prod6k = 6 * i;
    primes.add(prod6k - 1);
    primes.add(prod6k + 1);
}
for (int i = 0; i < primes.size(); i++) {
    int k = primes.get(i);
    //remove all the factors of the numbers generated by the formula
    for(int j = k * k; j <= n; j += k)//changed to k * k from 2 * k, Thanks to DTing
    {           
        int index = primes.indexOf(j); 
        if(index != -1)
            primes.remove(index);
    }
}
System.out.println(primes);

However, this method does generate the prime numbers correctly. This runs in a much faster way as we need not check for all the numbers which we do check in a Sieve.

My question is that am I missing any edge case? This would be a lot better but I never saw someone using this. Am I doing something wrong?

Can this approach be much more optimized?


Taking a boolean[] instead of an ArrayList is much faster.

int n = 100000000;
boolean[] primes = new boolean[n + 1];
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;
        }
      }
}
for (int i = 0; i <= n; i++)
    if (primes[i]) 
        System.out.print(i + " ");
Polypeptide answered 5/8, 2015 at 16:16 Comment(7)
to analyze your algorithm, always check its run times at more than one size point (preferably 3 or 4) and apply the empirical orders of growth analysis. for generating n primes, if it behaves as ~n^1.1, you're good; below ~n^1.5 is so-so, ~n^2 is way too slow. which is yours?Gunstock
@WillNess Thank you for that. Any suggestions for improving the algorithm?Polypeptide
first please tell us, which e.o.g. is your code. second, consult this canonical primes Java answer.Gunstock
You don't need to explicitly add 2 or 3. As @durron597 pointed out, your 6k +/- 1 formula removes them automatically. You'll never generate a multiple of 2 or of 3 using your formula.Arborvitae
Consider posting to codereview.stackexchange.com if you want a more comprehensive look at performance.Arborvitae
@ErickG.Hagstrom We have to, because 2 and 3 are primes, what removed are the multiples of 2 and 3, not 2 and 3.Polypeptide
No, you don't have to remove multiples of 2 and 3. Your formula will never generate a multiple of 2 or 3.Arborvitae
S
4

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<Integer> notPrimes = new HashSet<>();
    ArrayList<Integer> 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<Integer> primes, Set<Integer> 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<Integer> primesTo(int n) {
  List<Integer> 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<Integer> 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<Integer> primesList = new ArrayList<>();
  for (int i = 0; i <= n; i++)
    if (primes[i])
      primesList.add(i);

  return primesList;
}

public static List<Integer> bitPacking(int n) {
  List<Integer> 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<Integer> 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<Integer> 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
Sagesagebrush answered 5/8, 2015 at 17:16 Comment(1)
Interesting answer. ThanksPolypeptide
D
5

5 is the first number generated by your criteria. Let's take a look at the numbers generated up to 25:

5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25

Now, let's look at these same numbers, when we use the Sieve of Eratosthenes algorithm:

5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25

After removing 2:

5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25

After removing 3:

5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25

This is the same as the first set! Notice they both include 25, which is not prime. If we think about it, this is an obvious result. Consider any group of 6 consecutive numbers:

6k - 3, 6k - 2, 6k - 1, 6k, 6k + 1, 6k + 2

If we factor a little, we get:

3*(2k - 1), 2*(3k - 1), 6k - 1, 6*(k), 6k + 1, 2*(3k + 1)

In any group of 6 consecutive numbers, three of them will be divisible by two, and two of them will be divisible by three. These are exactly the numbers we have removed so far! Therefore:

Your algorithm to only use 6k - 1 and 6k + 1 is exactly the same as the first two rounds of the Sieve of Erathosthenes.

It's a pretty nice speed improvement over the Sieve, too, because we don't have to add all those extra elements just to remove them. This explains why your algorithm works and why it doesn't miss any cases; because it's exactly the same as the Sieve.


Anyway, I agree that once you've generated primes, your boolean way is by far the fastest. I have set up a benchmark using your ArrayList way, your boolean[] way, and my own way using LinkedList and iterator.remove() (because removals are fast in a LinkedList. Here's the code for my test harness. Note that I run the test 12 times to ensure that the JVM is warmed up, and I print the size of the list and change the size of n to attempt to prevent too much branch prediction optimization. You can also get faster in all three methods by using += 6 in the initial seed, instead of prod6k:

import java.util.*;

public class PrimeGenerator {
  public static List<Integer> generatePrimesArrayList(int n) {
    List<Integer> primes = new ArrayList<>(getApproximateSize(n));
    primes.add(2);// explicitly add
    primes.add(3);// 2 and 3

    for (int i = 6; i <= n; i+=6) {
      // get all the numbers which can be generated by the formula
      primes.add(i - 1);
      primes.add(i + 1);
    }

    for (int i = 0; i < primes.size(); i++) {
      int k = primes.get(i);
      // remove all the factors of the numbers generated by the formula
      for (int j = k * k; j <= n; j += k)// changed to k * k from 2 * k, Thanks
                                         // to DTing
      {
        int index = primes.indexOf(j);
        if (index != -1)
          primes.remove(index);
      }
    }
    return primes;
  }

  public static List<Integer> generatePrimesBoolean(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 = 6; i <= n; i+=6) {
      primes[i + 1] = true;
      primes[i - 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;
        }
      }
    }

    int approximateSize = getApproximateSize(n);
    List<Integer> primesList = new ArrayList<>(approximateSize);
    for (int i = 0; i <= n; i++)
      if (primes[i])
        primesList.add(i);

    return primesList;
  }

  private static int getApproximateSize(int n) {
    // Prime Number Theorem. Round up
    int approximateSize = (int) Math.ceil(((double) n) / (Math.log(n)));
    return approximateSize;
  }

  public static List<Integer> generatePrimesLinkedList(int n) {
    List<Integer> primes = new LinkedList<>();
    primes.add(2);// explicitly add
    primes.add(3);// 2 and 3

    for (int i = 6; i <= n; i+=6) {
      // get all the numbers which can be generated by the formula
      primes.add(i - 1);
      primes.add(i + 1);
    }

    for (int i = 0; i < primes.size(); i++) {
      int k = primes.get(i);
      for (Iterator<Integer> iterator = primes.iterator(); iterator.hasNext();) {
        int primeCandidate = iterator.next();
        if (primeCandidate == k)
          continue; // Always skip yourself
        if (primeCandidate == (primeCandidate / k) * k)
          iterator.remove();
      }
    }
    return primes;
  }

  public static void main(String... args) {
    int initial = 4000;

    for (int i = 0; i < 12; i++) {
      int n = initial * i;
      long start = System.currentTimeMillis();
      List<Integer> result = generatePrimesArrayList(n);
      long seconds = System.currentTimeMillis() - start;
      System.out.println(result.size() + "\tArrayList Seconds: " + seconds);

      start = System.currentTimeMillis();
      result = generatePrimesBoolean(n);
      seconds = System.currentTimeMillis() - start;
      System.out.println(result.size() + "\tBoolean Seconds: " + seconds);

      start = System.currentTimeMillis();
      result = generatePrimesLinkedList(n);
      seconds = System.currentTimeMillis() - start;
      System.out.println(result.size() + "\tLinkedList Seconds: " + seconds);
    }
  }
}

And the results of the last few trials:

3432    ArrayList Seconds: 430
3432    Boolean Seconds: 0
3432    LinkedList Seconds: 90
3825    ArrayList Seconds: 538
3824    Boolean Seconds: 0
3824    LinkedList Seconds: 81
4203    ArrayList Seconds: 681
4203    Boolean Seconds: 0
4203    LinkedList Seconds: 100
4579    ArrayList Seconds: 840
4579    Boolean Seconds: 0
4579    LinkedList Seconds: 111
Depressive answered 7/8, 2015 at 22:32 Comment(0)
S
4

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<Integer> notPrimes = new HashSet<>();
    ArrayList<Integer> 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<Integer> primes, Set<Integer> 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<Integer> primesTo(int n) {
  List<Integer> 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<Integer> 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<Integer> primesList = new ArrayList<>();
  for (int i = 0; i <= n; i++)
    if (primes[i])
      primesList.add(i);

  return primesList;
}

public static List<Integer> bitPacking(int n) {
  List<Integer> 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<Integer> 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<Integer> 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
Sagesagebrush answered 5/8, 2015 at 17:16 Comment(1)
Interesting answer. ThanksPolypeptide
A
2

There are several things that could be optimized.

For starters, the "contains" and "removeAll" operations on an ArrayList are rather expensive operations (linear for the former, worst case quadratic for the latter) so you might not want to use the ArrayList for this. A Hash- or TreeSet has better complexities for this, being nearly constant (Hashing complexities are weird) and logarithmic I think

You could look into the sieve of sieve of Eratosthenes if you want a more efficient sieve altogeter, but that would be besides the point of your question about the 6k +-1 trick. It is slightly but not noticably more memory expensive than your solution, but way faster.

Ascendancy answered 5/8, 2015 at 16:24 Comment(6)
I used the Sieve of Erastosthnes approach. Thank you for the hashTree approach though.Polypeptide
Let me wait for other answers. Will accept definitely if I feel yours was best.Polypeptide
are you saying that the OP code is not the sieve of Eratoshenes?Gunstock
He is not, at least not exactly. For the sieve, you generally allocate an array of booleans and stripe the non-primes out.Ascendancy
@BertPeters Sieve doesn't only mean taking a boolean array. It means cancelling out the multiples of a number, leaving the primes only.Polypeptide
@UmaKanth sieve of Eratosthenes means enumerating the multiples of each prime; in order to be removed from naturals above 1; to be left with primes. your code does exactly that. Eratosthenes had no Booleans, and no arrays either, and we don't even know whether he worked on one contiguous area or stopped in the middle, and worked by segments. that's all side details.Gunstock
V
1

Can this approach be much more optimized?

The answer is yes.

I'll start by saying that it is a good idea to use the sieve on a subset of number within a certain range, and your suggesting is doing exactly that.

Reading about generating Primes:

...Furthermore, based on the sieve formalisms, some integer sequences (sequence A240673 in OEIS) are constructed which they also could be used for generating primes in certain intervals.

The meaning of this paragraph is that your approach of starting with a reduced list of integers was indeed adopted by the academy, but their techniques are more efficient (but also, naturally, more complex).

Vilipend answered 5/8, 2015 at 16:45 Comment(0)
B
1

You can generate your trial numbers with a wheel, adding 2 and 4 alternately, that eliminates the multiplication in 6 * k +/- 1.

public void primesTo1000() {
  Set<Integer> notPrimes = new HashSet<>();
  ArrayList<Integer> primes = new ArrayList<>();
  primes.add(2);  //explicitly add
  primes.add(3);  //2 and 3

  int step = 2;
  int num = 5  // 2 and 3 already handled.
  while (num < 1000) {     
    handlePossiblePrime(num, primes, notPrimes);
    num += step;      // Step to next number.
    step = 6 - step;  // Step by 2, 4 alternately.
  }
  System.out.println(primes);
}
Busty answered 5/8, 2015 at 20:15 Comment(1)
Thank you. However this is taking more time than multiplying. I don't know whyPolypeptide
O
1

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<Integer> 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.

Obstetric answered 13/8, 2015 at 6:54 Comment(0)
F
1

This method below shows how to find prime nos using 6k+/-1 logic

this was written in python 3.6

def isPrime(n):
    if(n<=1):
        return 0
    elif(n<4):   #2 , 3 are prime
        return 1
    elif(n%2==0):  #already excluded no.2 ,so any no. div. by 2 cant be prime
        return 0
    elif(n<9):   #5, 7 are prime and 6,8 are excl. in the above step
        return 1
    elif(n%3==0):
        return 1

    f=5         #Till now we have checked the div. of n with 2,3 which means with 4,6,8 also now that is why f=5
    r=int(n**.5)    #rounding of root n, i.e: floor(sqrt(n))    r*r<=n
    while(f<=r):
        if(n%f==0): #checking if n has any primefactor lessthan sqrt(n), refer LINE 1
            return 0
        if(n%(f+2)==0): #remember her we are not incrementing f, see the 6k+1 rule to understand this while loop steps ,you will see that most values of f are prime
            return 0
        f=f+6

    return 1    

def prime_nos():
    counter=2  #we know 2,3 are prime
    print(2)
    print(3)   #we know 2,3 are prime
    i=1
    s=5  #sum  2+3
    t=0

    n=int(input("Enter the upper limit( should be > 3: "))

    n=(n-1)//6   #finding max. limit(n=6*i+1) upto which I(here n on left hand side) should run
    while(i<n):#2*(10**6)):
        if (isPrime(6*i-1)):   
            counter=counter+1
            print(6*i-1)  #prime no                                                

        if(isPrime(6*i+1)):    
           counter=counter+1
           print(6*i+1)  #prime no                                

        i+=1

prime_nos()  #fn. call
Fann answered 23/6, 2018 at 8:20 Comment(0)
K
0

Your prime number formula mathematically incorrect ex. take 96 it dividable to 6 96/6=16 so by this logic 97 and 95 must be prime if square root passed but square root of 95 is 9.7467... (passed) so its "prime". But 95 clearly dividable by 5 fast algorithm in c#

       int n=100000000;    
       bool [] falseprimes = new bool[n + 2];
       int ed=n/6;
        ed = ed * 6;
        int md = (int)Math.Sqrt((double)ed);
        for (int i = ed; i > md; i-=6)
        {
            falseprimes[i + 1] = true;
            falseprimes[i - 1] = true;

        }

        md = md / 6;
        md = md * 5;

        for (int i = md; i > 5; i -= 6)
        {
            falseprimes[i + 1] = true;
            falseprimes[i - 1] = true;

            falseprimes[(i + 1)* (i + 1)] = false;
            falseprimes[(i-1) * (i-1)] = false;
        }

        falseprimes[2] = true;
        falseprimes[3] = true;
Kitchenette answered 23/3, 2021 at 23:28 Comment(0)
U
0

To generate prime numbers using 6 * k + - 1 rule use this algorithm:

int n = 100000000;
int j,jmax=n/6;
boolean[] primes5m6 = new boolean[jmax+1];
boolean[] primes1m6 = new boolean[jmax+1];
for (int i = 0; i <= jmax; i++){
    primes5m6[i] = false;
    primes1m6[i] = false;
}
for (int i = 1; i <= (int)((Math.sqrt(n)+1)/6)+1; i++){
    if (!primes5m6[i]){
        for (j = 6*i*i; j <= jmax; j+=6*i-1){       
            primes5m6[j]=true;
            primes1m6[j-2*i]=true;
        }
        for (; j <= jmax+2*i; j+=6*i-1)       
            primes1m6[j-2*i]=true;
    }
    if (!primes1m6[i]){
        for (j = 6*i*i; j <= jmax-2*i; j+=6*i+1){      
            primes5m6[j]=true; 
            primes1m6[j+2*i]=true; 
        }
        for (; j <= jmax; j+=6*i+1)      
            primes5m6[j]=true;   
   }
}

System.out.print(2 + " ");
System.out.print(3 + " ");
for (int i = 1; i <= jmax; i++){
    if (!primes5m6[i]) 
        System.out.print((6*i-1) + " ");
    if (!primes1m6[i]) 
        System.out.print((6*i+1) + " ");
}
Ubangishari answered 11/4, 2021 at 14:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.