My code can only handle a range of about a million, whereas I need it to handle about 100 million to a billion.
I keep getting a memory error when I put in a range of 1 to 1 billion.
Is there any way I can optimise the code?
import time
from math import isqrt
def sieveprmcheck(n):
if n < 2:
return []
prime_num = [True] * (n + 1)
prime_num[0] = False
prime_num[1] = False
for i in range(2, isqrt(n) + 1):
if prime_num[i]:
for k in range(i * i, n + 1, i):
prime_num[k] = False
primes = [i for i in range(n + 1) if prime_num[i]]
return primes
def segsieve():
primes = sieveprmcheck(n)
prime = [True] * (n - m + 1)
for i in primes:
lower = (m // i)
if lower <= 1:
lower = i + i
elif (m % i) != 0:
lower = (lower * i) + i
else:
lower = lower * i
for j in range(lower, n + 1, i):
prime[j - m] = False
prime_numbers = []
for k in range(m, n + 1):
if prime[k - m]:
prime_numbers.append(k)
return prime_numbers
def palcheck(primes):
special_numbers = set()
for num in primes:
if str(num) == str(num)[::-1]: # Check if the number is a palindrome
special_numbers.add(num)
special_numbers_list = sorted(list(special_numbers))
print('Number of Special Numbers:', len(special_numbers_list), ':',
special_numbers_list[:3] + special_numbers_list[-3:])
return special_numbers_list
if __name__ == '__main__':
m = int(input('Please enter starting number: '))
n = int(input('Please enter ending number: '))
start = time.time()
primes = segsieve()
Special_Num = palcheck(primes)
end = time.time()
time_spent = end - start
print("\nTime spent:", time_spent, "seconds")
So it can calculate to a maximum of hundreds of millions but I was expecting to go from billions to trillions of primes.
As already recommended in the comments you can improve the sieve using wheel factorization.
This is an example that I created some time ago using a wheel of size 30 for the range of use you ask for. All multiples of 2 , 3 and 5 are not stored saving memory:
Result for N=10^9:
This is the segmented version to take up less memory: