3

I've made a sieve for generating primes. I'm doing a school project about RSA which includes some programming. I'll use the primes for an RSA system, but because it's for my essay the security isn't really important. However, big primes are much more challenging and I like that. The code I use:

def Zeef(a):
    import math
    upperBound = a
    upperBoundSquareRoot = int(math.sqrt(upperBound))
    isPrime = [1 for m in range (0,upperBound+1)]
    for m in range(2,upperBoundSquareRoot+1):
        if (isPrime[m]==1):
            for k in range(m*m,upperBound+1,m):
                isPrime[k] = 0;
    print("Priemgetallen : ")
    numberofPrimes = 0
    for m in range(2,upperBound+1):
        if (isPrime[m] ==1):
            print(m)
            numberofPrimes = numberofPrimes+1
    print("Aantal = " , numberofPrimes);
a=input("Alle priemgetallen tot: ")
aa=int(a)
Priemen = Zeef(aa)

I'm sure there is a faster way for generating primes, but i'm not really interested in improving my code right now.

When I'm running this function, it works fine for generating primes up to 7 digits, but when I want more, it's really slow. My computer (8gb ram) gives a message that there's not enough memory. I used the same algoritm in Processing, an other tool. Processing is really quick, but it doesn't recognize more than 10 digits. I also noticed the printing is slow when I'm generating primes which my computer is able to calculate.

I began searching on the internet and i found that i compiling my program would speed up the progress, but i'm not sure if it speeds up the calculation and printing part or just the interpreting part. I also found something about numpy wich was about arrays, but I'm not sure if this will notably speeds up my function.

How can I find my primes faster?

  • 1
    Google Translate gives me Dutch to English as follows: Zeef = Sieve; Priemgetallen = Primes; Aantal = Number; Alle priemgetallen tot = "All primes up"; Priemen = "Stab." Did it do a good job? :) (It corrected my initial guess of language, which was German.) – John Sep 16 '13 at 16:34
  • @Wooble That's the idea of the sieve: start with all numbers as candidate primes, the mark off those you know aren't. It's an integral part of the algorithm. – Jaime Sep 16 '13 at 17:13
  • It looks pretty good, compare to http://stackoverflow.com/questions/1042902/most-elegant-way-to-generate-prime-numbers/1043247#1043247 . Though for RSA you would use a probabilistic test like Miller-Rabin, maybe after sieving a few thousand candidates w.r.t. small primes. – starblue Sep 16 '13 at 19:27
  • [This](http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python) is a wonderful topic listing many ways to calculate primes and the speed thereof. It probably worth a read. – Daniel Sep 16 '13 at 19:53

3 Answers3

2

Here's an unoptimized version of your Sieve of Erathostenes, using numpy. On my 8GB laptop running 64 bit versions of Python (2.7) and Numpy (1.7), it computes the prime factors up to 10^9 in under a minute:

import numpy as np

def sieve(a):
    upper_bound = np.int(np.sqrt(a))
    is_prime = np.ones((a+1,), dtype=np.bool)
    for m in xrange(2, upper_bound+1):
        if is_prime[m]:
            is_prime[m*m::m] = False
    return np.where(is_prime)[0][2:]

>>> sieve(100)
array([ 2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59,
       61, 67, 71, 73, 79, 83, 89, 97], dtype=int64)

And here are my timings:

%timeit sieve(10**9)
1 loops, best of 3: 33.4 s per loop

%timeit sieve(10**8)
1 loops, best of 3: 2.47 s per loop

%timeit sieve(10**7)
1 loops, best of 3: 207 ms per loop

%timeit sieve(10**6)
100 loops, best of 3: 7.47 ms per loop

%timeit sieve(10**5)
1000 loops, best of 3: 716 us per loop

You could make it run about twice as fast by removing all the even numbers from the sieve, but even with that and all the memory in the world, you are still looking at several minutes to get all the primes up to 10^10.

Jaime
  • 59,107
  • 15
  • 108
  • 149
1

You're talking about an issue of computational complexity. There comes a point, with certain problems, where you will be unable to speed up your algorithm no matter how fast your processor or compiler is. For example, if you were trying to solve an NP-complete problem, it would be easy for small values, but hard for larger values.

I recommend you improve your code, even if you don't want to. Or, find a library that handles prime generation on its own. Here is an interesting link: http://rebrained.com/?p=458

That seems to be pretty good code for generating primes...but it doesn't generate large primes either (I tried it on my very fast iMac). It was quick up to about 100000. I recommend looking at this SO question for insights into how to test a randomly generated large number for primality.

Community
  • 1
  • 1
Philip White
  • 232
  • 2
  • 13
1

You will need a better algorithm than the Sieve of Eratosthenes if you want to generate the kinds of large prime numbers needed for the RSA algorithm. Here's an implementation of the Miller-Rabin primality checker for Python:

def isPrime(n):
    def isSpsp(n, a):
        d, s = n - 1, 0
        while d % 2 == 0: d, s = d / 2, s + 1
        t = pow(a, d, n)
        if t == 1: return True
        while s > 0:
            if t == n - 1: return True
            t, s = (t * t) % n, s - 1
        return False
    ps = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
         43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
    if n in ps: return True
    for p in ps:
        if not isSpsp(n, p): return False
    return True

If you're interested in programming with prime numbers, I modestly recommend this essay at my blog; you might also look at some of the other pages at my blog, including this one on generating RSA semi-primes.

user448810
  • 16,364
  • 2
  • 31
  • 53
  • I figured out the RAM is what limits my algorithm. Since my array has to contain 10^8 values, this is what my computer cannot handle because it only has 8gb of RAM. If I want to generate big primes (10^8+), the Sieve of Erathostenes is really just inefficient. If I calculate all the primes under 10^7 which this algorithm should be able to, I can check if a integer is prime or not by dividing the check number by all the primes found with my Sieve. I can find primes up to 10^14 with this method. Am I right about the fact that it's really hard to find primes bigger than 10^9 quickly? – user2784582 Sep 16 '13 at 21:15
  • No. To find a large prime quickly, input an odd number to the isPrime function described above. If it returns True, you are done. If it returns False, add 2 to the number and try again. It shouldn't take too long to find a prime number. The Miller-Rabin algorithm should be able to check several hundred numbers per second. – user448810 Sep 17 '13 at 00:00
  • By the way, you can sieve higher than 10^7. The trick is to compute the sieving primes in advance, then run the sieve in segments that fit into memory. See [http://stackoverflow.com/questions/10249378/](http://stackoverflow.com/questions/10249378/) for explanation and code. If you're clever you can even sieve at very large numbers, say 10^50 or larger; see this [post](http://programmingpraxis.com/2013/08/27/two-sieving-problems/) at my blog to find out how. – user448810 Sep 17 '13 at 00:03