Синтаксис в порядке (в Python 2). У семантики есть некоторые осложнения, которых можно избежать, и эта ошибка:
for x in range(2,int(sqrt(num))):
if( num % x == 0 ):
flag = False
range(2, Y)
переходит от 2 включенных к Y
исключенных - поэтому вы часто не проверяете последний возможный делитель и тем самым считаете «простыми числами» многие числа, которых нет. Как самое простое исправление, попробуйте 1 + int(...
в этом range
. После чего целесообразно устранить эти возможные осложнения: например,
if somebool: return True
else: return False
никогда не гарантируется, так как более простой return somebool
выполняет ту же работу.
Упрощенная версия всего вашего кода (только с необходимыми оптимизациями, но в остальном точно такой же алгоритм) может быть, например:
from math import sqrt
def isPrime(num):
for x in range(3, int(1 + sqrt(num)), 2):
if num % x == 0: return False
return True
def main():
i, n = 0, 3
end = 6
while i < end:
if isPrime(n):
i += 1
print n
n += 2
if __name__ == '__main__':
main()
«Возвращение, как только вы узнаете ответ», уже объяснено, я добавил еще одну важную оптимизацию (+ = 2 вместо 1 для n
, поскольку мы «знаем», что четные числа> 3 не являются простых чисел и настройка range
по той же причине).
Можно получить симпатичнее, например .:
def isPrime(num):
return all(num % x for x n range(3, int(1 + sqrt(num)), 2))
хотя это может показаться «проще», если вы не знакомы со встроенным all
, это действительно так, потому что это избавляет вас от необходимости (и читателей кода, которым необходимо следовать) низкоуровневой логики, в пользу соответствующего уровня абстракции для выражения ключевой идеи функции, то есть «num является простым, если все возможные нечетные делители имеют остаток [[non-0]] при попытке деления» (т. е. выражают концепцию напрямую в точной, исполняемой форме). Алгоритм внутри фактически все еще идентичен.
Идем дальше ...:
import itertools as it
def odd():
for n in it.count(1):
yield n + n + 1
def main():
end = 5
for i, n in enumerate(it.ifilter(isPrime, odd())):
print n
if i >= end: break
Опять же, это тот же алгоритм, что и раньше, только выраженный на более подходящем уровне абстракции: генерация последовательности нечетных чисел (от 3 и выше), помещенных в собственный генератор odd
, и некоторое использование встроенных функций enumerate
и itertools
, чтобы избежать неуместных (и ненужных) низкоуровневых выражений / рассуждений.
Повторюсь: фундаментальной оптимизации пока не применено - просто подходящая абстракция. Оптимизация неограниченной последовательной генерации простых чисел в Python (например, с помощью открытого сита Эратосфена) подробно обсуждалась в другом месте, например. здесь (не забудьте также проверить комментарии!). Здесь я сосредоточился на том, чтобы показать, как (с такими встроенными модулями, как enumerate
, all
и any
, критически важные itertools
, плюс генераторы и выражения генератора) многие проблемы зацикливания могут быть выражены в современном Python на более подходящих уровнях абстракции, чем «вдохновленные Си», которые могут показаться наиболее естественными для большинства программистов, которые привыкли к программированию на Си и т.п. (Возможно, к удивлению ученых, привыкших к «штрафу за абстракцию» в C ++, впервые определенному Степановым, Python обычно имеет вместо этого «премию за абстракцию», особенно если itertools
, хорошо известный своей невероятной скоростью, широко и соответствующим образом используется ... но это действительно другая тема; -).