Подтвердить что ты не робот

Производительность простого факторинга python

Я относительно новичок в python, и я запутался в производительности двух относительно простых блоков кода. Первая функция порождает простую факторизацию числа n, заданного списком простых чисел. Второй генерирует список всех факторов n. Я бы хотел, чтобы prime_factor был быстрее, чем factors (для одного и того же n), но это не так. Я не ищу лучших алгоритмов, но я хотел бы понять, почему prime_factor намного медленнее, чем factors.

def prime_factor(n, primes):
  prime_factors = []
  i = 0
  while n != 1:
      if n % primes[i] == 0:
          factor = primes[i]
          prime_factors.append(factor)
          n = n // factor
      else: i += 1
  return prime_factors

import math
def factors(n):
  if n == 0: return []
  factors = {1, n}
  for i in range(2, math.floor(n ** (1/2)) + 1):
      if n % i == 0:
          factors.add(i)
          factors.add(n // i)
  return list(factors)

Используя модуль timeit,

{ i:factors(i) for i in range(1, 10000) } занимает 2,5 секунды

{ i:prime_factor(i, primes) for i in range(1, 10000) } занимает 17 секунд

Это удивительно для меня. factors проверяет каждое число от 1 до sqrt (n), а prime_factor проверяет только числа. Я был бы признателен за любую помощь в понимании характеристик производительности этих двух функций.

Спасибо

Изменить: (ответ на roliu) Вот мой код для генерации списка простых чисел от 2 до up_to:

def primes_up_to(up_to):
  marked = [0] * up_to
  value = 3
  s = 2
  primes = [2]
  while value < up_to:
      if marked[value] == 0:
          primes.append(value)
          i = value
          while i < up_to:
              marked[i] = 1
              i += value
      value += 2
  return primes
4b9b3361

Ответ 1

Не видя, что вы использовали для primes, мы должны угадать (мы не можем запустить ваш код).

Но большая часть этого - просто математика: есть (очень грубо говоря) около n/log(n) простых чисел меньше n, и это намного больше, чем sqrt(n). Поэтому, когда вы передаете штрих, prime_factor(n) делает намного больше работы: он проходит через операции O(n/log(n)) перед тем, как найти первый простой коэффициент (n сам!), А factors(n) отбрасывается после операций O(sqrt(n)).

Это может быть очень значительным. Например, sqrt(10000) составляет всего 100, но есть 1229 простых чисел меньше 10000. Таким образом, prime_factor(n) может выполнить более 10 раз больше работы для работы с большими штрихами в вашем диапазоне.