Search code examples
pythonprimes

Python Finding Mersenne primes with Lucas-Lehmer sequence and storing them


I am trying to calculate big primes (for fun) on my computer. So far, I have got to a point where it can calculate the primes. However, I am wondering how I can store them and make it so that when the code restarts it continues where it left off. Here is my code:

lucas_lehmer = [4]

def mersenne(n):
    return (2 ** n) - 1

def ll(n):
    global lucas_lehmer
    if len(lucas_lehmer) < n:
        for num in range(n-1):
            lucas_lehmer.append(lucas_lehmer[-1] ** 2 - 2)
    return lucas_lehmer[n-1]

def check_prime(n):
    m = mersenne(n)
    if ll(n - 1) % m == 0:
        return m
    else:
        return -1

It calculates primes using the Lucas-Lehmer seqence. The sequence starts with 4 and the next number is the number squared, minus 2. Also, the input to the check_prime function must also be a prime number.


Solution

  • You're algorithm is suffiently slow that storing and restarting won't be of much value as it bottoms out quickly. However, it's still a good exercise.

    First, this line in your code isn't optimal:

    for num in range(n-1):
    

    As it can cause you to add more items to the lucas_lehmer array than you need to answer the immediate question. It should be more like:

    while len(lucas_lehmer) < n:
    

    or the difference between the length of the array and the number you're testing.

    What you need to store, in my understanding of this code, is not the primes but your lucas_lehmer array so that you don't have to build it up again upon restart of the code. That's the approach I take below:

    library lucas_lehmer.py

    import pickle
    
    PICKLE_FILE = "lucas_lehmer.pickle"
    
    lucas_lehmer = None
    
    def ll(n):
        global lucas_lehmer
    
        if lucas_lehmer is None:
            try:
                with open(PICKLE_FILE, 'rb') as file:
                    lucas_lehmer = pickle.load(file)
            except FileNotFoundError:
                lucas_lehmer = [4]
    
        if len(lucas_lehmer) < n:
            while len(lucas_lehmer) < n:
                lucas_lehmer.append(lucas_lehmer[-1] ** 2 - 2)
    
            with open(PICKLE_FILE, 'wb') as file:
                pickle.dump(lucas_lehmer, file)
    
        return lucas_lehmer[n - 1]
    
    def check_prime(n):
        mersenne = (2 ** n) - 1
    
        if ll(n - 1) % mersenne == 0:
            return mersenne
    
        return -1
    

    This code will create the lucas_lehmer.pickle file for you if it doesn't exist. I tried this with JSON but it got slower slightly sooner with large integers than did Pickle. Now, you also need test code that you start, stop and restart:

    from lucas_lehmer import check_prime
    
    def is_prime(n):
        if n < 2:
            return False
    
        if n % 2 == 0:
            return n == 2
    
        for divisor in range(3, int(n ** 0.5) + 1, 2):
            if n % divisor == 0:
                return False
    
        return True
    
    while True:
        number = int(input("Enter a number: "))
    
        if number < 0:
            break
    
        if is_prime(number):
            print(number, check_prime(number))
        else:
            print(number, "not prime!")
    

    The key to this is you need to instrument your library to make sure that it's initializing, loading and dumping correctly.