Сводные описания являются мощным инструментом в Python. Думайте о них как о петле в стероидах. :-) Вы можете использовать их для реализации пробного деления, что является простым способом поиска простых чисел.
Это работает так:
In [4]: sum(prime_list(100))
Out[4]: 1061
В prime_list
функции:
def prime_list(num):
"""Returns a list of all prime numbers up to and including num.
Based on trial division.
:num: highest number to test
:returns: a list of primes up to num
"""
if num < 3:
raise ValueError('this function only accepts arguments > 2')
candidates = range(3, num+1, 2) # (a)
L = [c for c in candidates if all(c % p != 0 for p in range(3, c, 2))] #(b)
return [1, 2] + L
Теперь для объяснения. За исключением 2, все простые числа нечетны.Таким образом, все нечетные числа от 3 до num
(100 в этом случае) являются кандидатами на простые числа. Давайте создать список тех, кто, как это сделано в (а):
In [5]: num = 100
In [6]: range(3, num+1, 2)
Out[6]: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]
Для нечетного числа c
быть простым, необходимо обеспечить, чтобы c
по модулю всех предыдущих нечетных чисел p
должен быть отличен от нуля. Скажем c
является 25.
In [7]: c = 25
Тогда p
в:
In [8]: range(3, c, 2)
Out[8]: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23]
Теперь проверьте c
по модулю p
:
In [9]: [c % p != 0 for p in range(3, c, 2)]
Out[9]: [True, False, True, True, True, True, True, True, True, True, True]
Как мы знаем, 25% 5 == 0, поэтому второй элемент в списке - False
. Однако для числа, которое должно быть простым, все элементы в списке должны быть правдой:
In [10]: all(c % p != 0 for p in range(3, c, 2))
Out[10]: False
Таким образом, 25 не является простым.
Давайте попробуем еще раз для c
41:
In [11]: c = 41
In [12]: range(3, c, 2)
Out[12]: [3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39]
In [13]: [c % p != 0 for p in range(3, c, 2)]
Out[13]: [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
In [14]: all(c % p != 0 for p in range(3, c, 2))
Out[14]: True
И в самом деле 41 является простым.
Так prime_list возвращает список простых чисел:
In [15]: prime_list(100)
Out[15]: [1, 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]
Обобщая, что выше мы просто используем sum()
функцию:
In [16]: sum(prime_list(100))
Out[16]: 1061
Edit: На основе комментариев, я попробовал улучшение что WillNess предлагает и реальное сито с использованием комплектов:
def prime_list(num):
if num < 3:
raise ValueError('this function only accepts arguments > 2')
candidates = range(3, num+1, 2)
L = [c for c in candidates if all(c % p != 0 for p in range(3, c, 2))]
return [1, 2] + L
def prime_list2(num):
if num < 3:
raise ValueError('this function only accepts arguments > 2')
candidates = range(3, num+1, 2)
L = [c for c in candidates if all(c % p != 0 for p in
range(3, int(math.sqrt(c))+1, 2))]
return [1, 2] + L
def prime_list3(num):
candidates = set(range(3, num+1, 2))
results = [1, 2]
while candidates:
t = list(candidates)[0]
results.append(t)
candidates -= set(range(t, num+1, t))
return results
Некоторые тайминги для num=100
:
In [8]: %timeit prime_list(100)
1000 loops, best of 3: 180 us per loop
In [9]: %timeit prime_list2(100)
1000 loops, best of 3: 192 us per loop
In [10]: %timeit prime_list3(100)
10000 loops, best of 3: 83.9 us per loop
И num=1000
:
In [11]: %timeit prime_list(1000)
100 loops, best of 3: 8.05 ms per loop
In [12]: %timeit prime_list2(1000)
100 loops, best of 3: 2.43 ms per loop
In [13]: %timeit prime_list3(1000)
1000 loops, best of 3: 1.26 ms per loop
num = 5000
:
In [14]: %timeit prime_list(5000)
1 loops, best of 3: 166 ms per loop
In [15]: %timeit prime_list2(5000)
100 loops, best of 3: 11.1 ms per loop
In [16]: %timeit prime_list3(5000)
100 loops, best of 3: 15.3 ms per loop
И наконец num=50000
:
In [18]: %timeit prime_list3(50000)
1 loops, best of 3: 1.49 s per loop
In [19]: %timeit prime_list2(50000)
1 loops, best of 3: 170 ms per loop
У вас есть код, о котором вы писали? – debianplebian
Что значит? код выше, или вы имеете в виду код, который генерировал список простых чисел. –
@kyle_k Я имел в виду, что у вас есть код для суммирования списка, но я добавил, что делать ниже. – debianplebian