-1

I'm using the following code to test for prime numbers.

def primes(n):
    """ Returns  a list of primes < n """
    sieve = [True] * n
    for i in xrange(3,int(n**0.5)+1,2):
        if sieve[i]:
            sieve[i*i::2*i]=[False]*((n-i*i-1)/(2*i)+1)
    yield [2] + [i for i in xrange(3,n,2) if sieve[i]]


outfile = open('primes','w')
input = input("Feed Me:")

outfile.write(str(primes(input)))
print "Done"

Is there a simple way of getting a count of the prime numbers generated. As opposed to printing the actual numbers? Also could this code be made to generate prime numbers above 100000000 without overflowing?

user34981
  • 37
  • 1
  • 1
  • 5
  • https://primes.utm.edu/howmany.html – Grijesh Chauhan Feb 12 '15 at 07:14
  • FWIW, your code only yields a single object (a list), so you should change that `yield` to `return`. The `yield` statement is used to make a generator; see [the docs](https://wiki.python.org/moin/Generators) for further info. – PM 2Ring Feb 12 '15 at 07:29
  • Yeah that happened while I was mucking around. I changed some code and had to change it back. I then posted the dumb version. :( – user34981 Feb 12 '15 at 11:56

1 Answers1

1

You can drop every even number from the table, just integer divide by 2 to store the odd numbers only. sum works with booleans mapping them to ints: True is 1 and False is 0; notice that this works even without 2 in table for n >= 2 because 1 is marked as a prime in the table ;)

def n_primes(n):
    """ Returns  the number of primes < n """
    sieve = [True] * (n//2)
    for i in xrange(3,int(n**0.5) + 1,2):
        if sieve[i//2]:
            sieve[i*i//2::i]=[False]*((n-i*i-1)/(2*i)+1)

    return sum(sieve)

or even better, count the primes encountered:

def n_primes(n):
    """ Returns  the number of primes < n (for n > 2)"""
    n_p = 1  # 2 is a prime
    sieve = [True] * (n//2)
    for i in xrange(3,int(n**0.5) + 1,2):
        if sieve[i//2]:
            n_p += 1
            sieve[i*i//2::i]=[False]*((n-i*i-1)/(2*i)+1)

    return n_p

Notice, that your sieve function does not return a list but a generator, that yields the result, you probably wanted to write the original code as

def primes(n):
    """ Returns  a list of primes < n """
    sieve = [True] * n
    for i in xrange(3,int(n**0.5)+1,2):
        if sieve[i]:
            sieve[i*i::2*i]=[False]*((n-i*i-1)/(2*i)+1)

    return [2] + [i for i in xrange(3,n,2) if sieve[i]]

or using my generator version:

def primes(n):
    """ Yields a sequence of primes < n """
    if n <= 2:
        return

    yield 2
    sieve = [True] * (n//2)
    for i in xrange(3,int(n**0.5) + 1,2):
        if sieve[i//2]:
            yield i
            sieve[i*i//2::i] = [False] * ((n-i*i-1)/(2*i)+1)

In the case of the first, you can do len(primes(n)) to get the number (though this is wasteful), for the second do sum(1 for i in primes(n))


As for generating prime numbers above 100000000, the sieve table would spend (4 * n / 2) bytes on 32-bit processor and 8 * n / 2 on 64-bit processor, so your mileage might vary... One would want to use some kind of bitarray though one is not built-in in python.

  • Good so far, but I still get a memory error around the 1000000000 mark. The number I'm ultimately going for is: 18446744073709551615 – user34981 Feb 12 '15 at 07:50
  • 2
    Good luck. 18446744073709551615 is 2^64 bits, to store the sieve you need 2^60 bytes, which incidentally is 1048576 TiB. With current hard disk prices it will cost about 35 million dollars to store this data. – Antti Haapala -- Слава Україні Feb 12 '15 at 07:57
  • Of course you can use a sieve that does not require ~O(N) of bits, but instead use computation to offset for the lack of space, now a Pritchard sieve could fit in RAM; if you are lucky enough to have a really fast system that can test millions of numbers in a second with that, you could expect your program to finish before year 2100. Better to buy a good UPS though. – Antti Haapala -- Слава Україні Feb 12 '15 at 08:08
  • I wasn't expecting a fast answer to my prime numbering madness. But It's looking like I'm not going to get any insight at all with my tiny CPU here. Does anybody know of a publicly accessible data on prime numbers that I can grep for numbers below 18446744073709551615? – user34981 Feb 12 '15 at 08:40
  • It's occurred to me I should probably share a bit more about my ultimate objective. I'm trying to determine if I can derive the ability to factor any number up to 2^64. I was thinking the fastest way to do this would be to keep a table of primes handy, if possible. Since I was reasonably sure the answer might be no. I was looking to generate the table and then look at ways of cutting it down to size. – user34981 Feb 12 '15 at 09:10
  • It is possible to also calculate the approximation of number of primes under `n` with the [π(x) approximation](http://en.wikipedia.org/wiki/Prime-counting_function), for example `x / ln x` gets within 1.7 % at 10^26 – Antti Haapala -- Слава Україні Feb 12 '15 at 09:13
  • 1
    You can use [this code](http://stackoverflow.com/a/26440674/4014959) I posted last year to find large primes in a range, eg `python range_sieve6.py 1234567890000 1234567890100` returns `[1234567890007L, 1234567890019L, 1234567890041L, 1234567890089L, 1234567890097L]` in 3.5 seconds on my 2GHz machine. But it won't be useful for investigating numbers of the **huge** size you're interested in. – PM 2Ring Feb 12 '15 at 09:13
  • "The value for π(10^24) was originally computed by J. Buethe, J. Franke, A. Jost, and T. Kleinjung assuming the Riemann hypothesis.[10] It has since been verified unconditionally in a computation by D. J. Platt.[11]", so the value of `π(2^64)` is known by now... – Antti Haapala -- Слава Україні Feb 12 '15 at 09:18
  • Using mpmath, π(18446744073709551615) is approximately 425656284014012122, computed using `mp.riemannr()`. And `mp.primepi2()` returns the interval (4.2565627653473709e+17, 4.2565629169670016e+17). – PM 2Ring Feb 12 '15 at 09:30
  • 1
    @user34981: To factorize numbers < n² by trial division you can use a table of primes up to n. Eg, to factorize numbers up to 2^64 you'd use a table up to 2^32. That's not so bad - it's possible to store such a table with 30 numbers per byte (since all primes > 5 are of the form 30k±r with r in {1, 7, 11, 13}). FWIW, I have a database of primes up to 3000000000 here, so that's 100E6 bytes. However, performing those trial divisions for large numbers can take a _long_ time. – PM 2Ring Feb 12 '15 at 10:00
  • 1
    @user34981: Efficient factorization of large numbers requires fairly advanced mathematics. One popular algorithm is [Lenstra elliptic curve factorization](http://en.wikipedia.org/wiki/Lenstra_elliptic_curve_factorization). Also see http://en.wikipedia.org/wiki/Integer_factorization#Current_state_of_the_art – PM 2Ring Feb 12 '15 at 10:01