Вот что я бы сделал:
def prime_factors(x):
factors = []
while x % 2 == 0:
factors.append(2)
x /= 2
i = 3
while i * i <= x:
while x % i == 0:
x /= i
factors.append(i)
i += 2
if x > 1:
factors.append(x)
return factors
>>> prime_factors(600851475143)
[71, 839, 1471, 6857]
Это довольно быстро, и я думаю, что это правильно. Довольно просто взять максимум найденных факторов.
2017-11-08
Возвращаясь к этому 5 лет спустя, я бы использовал yield
и yield from
плюс более быстрый подсчет по простому диапазону:
def prime_factors(x):
def diver(x, i):
j = 0
while x % i == 0:
x //= i
j += 1
return x, [i] * j
for i in [2, 3]:
x, vals = diver(x, i)
yield from vals
i = 5
d = {5: 2, 1: 4}
while i * i <= x:
x, vals = diver(x, i)
yield from vals
i += d[i % 6]
if x > 1:
yield x
list(prime_factors(600851475143))
В диктовке {5: 2, 1: 4}
используется тот факт, что вам не нужно смотреть на все нечетные числа. Выше 3 все числа x % 6 == 3
кратны 3, поэтому вам нужно посмотреть только на x % 6 == 1
и x % 6 == 5
, и вы можете переключаться между ними, поочередно добавляя 2 и 4, начиная с 5.