Here's a Python 2 code that creates a file of primes packed in bytes, with each byte encoding a primitive block of 30 numbers, using the fact that all primes> 5 are coprime to 30 and therefore correspond to one of (1, 7, 11, 13, 17, 19, 23, 29) mod 30.
sieve_bin.py
And here is the program that reads the primebits file created by sieve_bin.py . The file is read in an array of unsigned bytes, so it is efficient in using RAM: one byte for each data byte read from the file, plus a little overhead for the array object itself (28 bytes on a 32-bit machine).
The main function of this program creates a list of primes using the isprime function. This is about 4 times slower than using a sieve, but it has much less memory overhead. You can probably speed it up a bit, but such optimizations will be left as an exercise for the reader. :)
isprime_bin.py
On my old single-core 2 GHz computer with 2 GB of RAM, it takes about 26 seconds for sieve_bin.py to create a primebits file for numbers <64000020 (file size = 2133334 bytes); approximately half of this time is spent sifting prime numbers. isprime_bin.py takes about 124 seconds to create a list of primes from this file (sending the output to / dev / null).
The result was verified by comparing it with the output generated by the regular Eratosthenes sieve program.
The code in isprime_bin.py designed to test arbitrary positive integers for primitiveness. To simply generate a list of primes, it can be significantly accelerated, because the first two if tests are applicable only to numbers <= 5. Here is a modified version that takes about 47 seconds to create a list of all primes from 2133334 bytes primebits .
#! /usr/bin/env python import sys import os.path from array import array def load_primes(fname): primebytes = array('B') filesize = os.path.getsize(fname) with open(fname, 'rb') as f: primebytes.fromfile(f, filesize) return primebytes prime_residues = (1, 7, 11, 13, 17, 19, 23, 29) #Build a dict for fast conversion of residue to bitmask bitmasks = dict((v, 1<<i) for i, v in enumerate(prime_residues)) def isprime(n, primebytes): r = n % 30 if r not in bitmasks: return False b = primebytes[n // 30] return b & bitmasks[r] def primes(primebytes): s = (2, 3, 5) + prime_residues[1:] for i in s: yield i s = prime_residues j = 30 while True: try: for i in s: p = j + i if isprime(p, primebytes): yield p j += 30 except IndexError: return #Test def main(): m = int(sys.argv[1]) if len(sys.argv) > 1 else 300 fname = 'primebits' primebytes = load_primes(fname) primelist = [] for p in primes(primebytes): if p > m: break primelist.append(p) print primelist if __name__ == '__main__': main()