Рубрики
Без рубрики

Сито Эратосфена в одной линии Python

Нахождение простых чисел имеет решающее значение для практических применений, таких как криптография. Многие методы общего клавиша являются только безопасными (с криптографической точки зрения), потому что это, как правило, неэффективно и медленно вычисляют главные факторы больших чисел. Простой алгоритм, чтобы проверить, является ли номер простом простое число n, это … Сито эратостено в одной строке Python Подробнее »

Автор оригинала: Chris.

Нахождение простых чисел имеет решающее значение для практических применений, таких как криптография. Многие методы общего клавиша являются только безопасными (с криптографической точки зрения), потому что это, как правило, неэффективно и медленно вычисляют главные факторы больших чисел.

Простой алгоритм, чтобы проверить, является ли номер главным

Prime Number N – это целочисленное число, которое не делится без остатка любого другого (целочисленного) номера, кроме 1 и п. Другими словами, нет двух целых чисел A и B такого, что их продукт равняется простому номеру: A *.

Скажем, вы хотите проверить определенное количество N, будь то простое число. Как вы это делаете? Начнем с наивного алгоритма, чтобы определить простые числа:

def prime(n):
    for i in range(2,n):
        if n % i == 0:
            return False
    return True


print(prime(10))
# False

print(prime(11))
# True

print(prime(7919))
# True

Алгоритм проверяет все номера между 2 и N, является ли этот номер дивизором номера N. Например, если вы хотите определить, является ли номерным числом, алгоритм быстро поймет, что для результата выражения N% I верно. Он нашел номер I, который является делителем N, поэтому N не может быть простым числом. Следовательно, алгоритм оставляет функцию и возвращает false.

Над алгоритм тесты на одно число n, лучше ли он. Сложность времени линейна на входе N: алгоритм нуждается в петле итерации (наихудший случай) для проверки того, является ли числовой N предпринимательным числом. Но что, если вы хотите рассчитать все простые числа от 2 до определенного максимального количества м? Просто, вы повторяете выше простой тест M-1 раз:

# Find all prime numbers 

Мы используем понимание списка (см. Главу 3), чтобы создать список со всеми простыми числами, меньшими, чем м. Из-за циклического цикла этот алгоритм требует функции M-1 IS_PRIME (N). Итак, сложность времени ограничена (M-1) * N

Есть ли другой способ?

Сито Эратосфена в одной линии кода Python

Напишите алгоритм, который более эффективен, чем выше наивывая реализация, чтобы найти все простые числа до максимального целочисленного числа m. Этот одноклассник вдохновлен древним алгоритмом, называемым «ситом эратосфена», который будет объяснен в оставшейся части этого раздела.

## Dependencies
from functools import reduce

## The Data
n=100

## The One-Liner
primes = reduce(lambda r, x: r - set(range(x**2, n, x)) if x in r else r, range(2, int(n**0.5) + 1), set(range(2,n)))

## The Result
print(primes)
# {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}

Листинг: одноклассное решение, реализующее сито эратосфена.

Если вы не совсем запутались этим одноклассником, ваше имя, вероятно, Guido Van Rossum (Создатель Python). Остальные из нас могут понадобиться некоторые фоновые знания, чтобы иметь возможность понять, что здесь происходит.

Как это устроено

Чтобы быть Фрэнком, этот одноклассник сбивает с толку, сложным и нечитаемым. Тем не менее, это тип кода, который вы сталкиваетесь на практике и с этой книгой, я хочу убедиться, что вы сможете понять каждую линейку кода – даже если это займет некоторое время. Нужно доказательство того, что люди пишут код как это на практике? Я наткнулся на этот одноклассник на Stackoverflow Отказ Он свободно на основе древнего алгоритма, называемого Сито Эратосфена Отказ Сито Эратосфена представляет собой древний и все еще очень популярный алгоритм для расчета простых чисел.

Перед тем, как мы погрузимся в код, давайте сначала попытаемся понять идею алгоритма. Алгоритм чрезвычайно прост: он создает (концептуально) огромный массив чисел от 2 до м, максимальный целочисленный номер. Затем он неоднократно отмечает числа в этом массиве, которые не являются простыми номерами. После окончания алгоритма все немаркированные номера являются простыми числами.

Для достижения этой цели алгоритм повторяет следующие шаги:

  • Начните с первого номера 2 и увеличивайте его на каждом этапе процесса, пока вы не найдете неподвижный номер X, который является Prime.
  • Отметьте все кратные цифры числа X, потому что они не являются Prime: номер X – это делитель всех этих чисел.
  • Простая оптимизация: начать маркировку кратных из числа x * x вместо 2x. Причина в том, что все номера между 2x и X * X уже отмечены (см. Ниже).

Визуальный алгоритм объяснил

Вот визуальный пошаговый пример алгоритма:

Рисунок: изначально все номера между 2 и не отмечаются (белые клетки). Первый немаркированный номер 2 – это простое число.

Рисунок: Отметьте все кратки для 2, потому что они не премьер. Игнорируйте заметные числа для остальной части алгоритма.

Рисунок: Перейти к следующему немаркеру № 3. Потому что он не отмечен на данный момент, это простое число. Затем отметьте все многополитенные 3. Начать маркировку из номера 3 * 3, потому что все кратные от 3 между 3 и уже отмечены.

Рисунок: Перейти к следующему безмасскуркуному номеру 5 (что является простойным числом). Затем отметьте все кратные 5. Начните маркировку с номера 5 * 5, потому что все кратные от 5 между 5 и уже отмечены.

Рисунок: Перейти к следующему безразмеренному номеру 7 (что является простым числом). Затем отметьте все кратки 7. Начните маркировку с номера 7 * 7, потому что все кратные 7 между 7 и уже отмечены.

Рисунок: Перейти к следующему немаркету № 11 (который является простым числом). Затем отметьте все кратные 11. Когда мы начали маркировку из числа, мы понимаем, что это уже больше, чем наше максимальное число. Следовательно, алгоритм прекратил. Все оставшиеся немаркивые номера не делимы по любому номеру и, следовательно, являются простыми числами.

Положить все это вместе

Этот алгоритм гораздо более эффективен, чем наивный алгоритм для вычисления всех простых чисел до определенного количества м. Почему? Потому что наивный алгоритм проверяет каждое число самостоятельно Будь то простое число – игнорирование всех предыдущих вычислений. В отличие от этого, сито Eratosthenes Reuses Результаты предыдущих вычислительных шагов – общая идея во многих областях алгоритмической оптимизации. Каждый раз, когда мы вычеркиваем краткое число, мы, по сути, мы экономите нас от утомительной работы проверки, является ли это несколько главным числом или нет: мы уже знаем, что это не так.

Хорошим вопросом, поэтому мы начинаем маркировку от квадрата простого числа вместо самого простого числа. Например, в приведенном выше алгоритме на рисунке 8-8 мы только что нашли простое число 7 и начать маркировку из числа. Причина в том, что мы уже отмечали все другие кратные в предыдущих итерациях: 2 * 7, 3 * 7, 4 * 7, 5 * 7, 6 * 7. Другими словами, мы уже отмечали все кратные цифры, которые меньше текущего простого числа 7: 2, 3, 4, 5, 6.

Оснащен тщательным концептуальным пониманием алгоритма, теперь мы можем начать раскрывать решение одноклассника:

## The One-Liner
primes = reduce(lambda r, x: r - set(range(x**2, n, x)) if x in r else r, range(2, int(n**0.5) + 1), set(range(2,n)))

Это очень элегантно, но вам нужно инвестировать некоторое время, чтобы понять это. Функция уменьшения требует три аргумента: Уменьшите (функционируйте, инициализатор). Вот соответствующее описание документации:

«Примените функцию двух аргументов, кумулятивно к элементам последовательности, слева направо, чтобы уменьшить последовательность к одному значению. Например, уменьшить (лямбда x, y: x + y, [1, 2, 3, 4, 5]) рассчитывает (((((1 + 2) +3) +4) +5). Левый аргумент, X, является накопленным значением и правильным аргументом, Y, это обновление Последовательность. Если присутствует дополнительный инициализатор, он размещен перед элементами последовательности в расчете и служит по умолчанию, когда последовательность пуста. Если инициализатор не дан и последовательность содержит Только один элемент, первый элемент возвращается. “

One-LiLER использует функцию «Уменьшить», чтобы удалить, один шаг за раз, все «помеченные» номера из исходного набора всех чисел между 2 и N (в одноклассном: Set (Range (2, N)))) Отказ Требуется этот набор в качестве начального значения для набора немаркированных значений R, так как изначально все значения не отображаются. Теперь он проходит через все номера X между 2 и квадратным корнем N (в одноиналке: диапазон (2, int (n ** 0,5) + 1)) и удаляет кратные X из множества R (начиная с x ** 2) – Но только если номер x – простое число (т. Е. Это не удаляется из набора R на данный момент во времени). Проведите 5-15 минут, чтобы перечитать это объяснение и внимательно изучить различные части одноклассника – я обещаю, что после вашей первоначальной путаницы вы найдете это упражнение, чтобы стоить ваше инвестированное время для того, чтобы вы значительно продвинулись ваш код Python понимание навыков.

Хотите ускорить навыки Python и станьте кодом следующего уровня? Стать мастером Python легко может быть самым прибыльным решением вашей карьеры!

Работая в качестве исследователя в распределенных системах, доктор Кристиан Майер нашел свою любовь к учению студентов компьютерных наук.

Чтобы помочь студентам достичь более высоких уровней успеха Python, он основал сайт программирования образования Finxter.com Отказ Он автор популярной книги программирования Python One-listers (Nostarch 2020), Coauthor of Кофе-брейк Python Серия самооставленных книг, энтузиаста компьютерных наук, Фрилансера и владелец одного из лучших 10 крупнейших Питон блоги по всему миру.

Его страсти пишут, чтение и кодирование. Но его величайшая страсть состоит в том, чтобы служить стремлению кодер через Finxter и помогать им повысить свои навыки. Вы можете присоединиться к его бесплатной академии электронной почты здесь.