Мой текущий алгоритм проверки простоты чисел в python - это способ замедления для чисел от 10 миллионов до 1 миллиарда. Я хочу, чтобы это улучшилось, зная, что я никогда не получу числа, превышающие 1 миллиард.
Ситуация в том, что я не могу получить реализацию, которая достаточно быстра для решения проблемы 60 проекта Эйлера: я получаю ответ на проблему за 75 секунд, где она мне нужна за 60 секунд. http://projecteuler.net/index.php?section=problems&id=60
У меня очень мало памяти, поэтому я не могу хранить все простые числа ниже 1 млрд.
В настоящее время я использую стандартное пробное деление, настроенное на 6k ± 1. Есть ли что-нибудь лучше, чем это? Нужно ли уже получать метод Рабина-Миллера для таких больших чисел?
primes_under_100 = [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]
def isprime(n):
if n <= 100:
return n in primes_under_100
if n % 2 == 0 or n % 3 == 0:
return False
for f in range(5, int(n ** .5), 6):
if n % f == 0 or n % (f + 2) == 0:
return False
return True
Как я могу улучшить этот алгоритм?
Точность: я новичок в python и хотел бы работать только с python 3+.
Окончательный код
Для тех, кому интересно, используя идеи MAK, я сгенерировал следующий код, который примерно на 1/3 быстрее, что позволяет мне получить результат проблемы Эйлера менее чем за 60 секунд!
from bisect import bisect_left
# sqrt(1000000000) = 31622
__primes = sieve(31622)
def is_prime(n):
# if prime is already in the list, just pick it
if n <= 31622:
i = bisect_left(__primes, n)
return i != len(__primes) and __primes[i] == n
# Divide by each known prime
limit = int(n ** .5)
for p in __primes:
if p > limit: return True
if n % p == 0: return False
# fall back on trial division if n > 1 billion
for f in range(31627, limit, 6): # 31627 is the next prime
if n % f == 0 or n % (f + 4) == 0:
return False
return True