我正在尝试使用Python找到给定数字(600851475143)的最大素数因子。我已经制作了以下代码,但问题是,它需要永远,可能是因为它遍历列表数百万次。如何优化这个过程?
def factors(n):
list = []
i = 1
while i < n:
if n % i == 0:
list.append(i)
i += 1
return list
def prime(n):
list = factors(n)
primelist = []
for item in list[1:]:
if item % 2 != 0 and item % 3 != 0 and item % 4 != 0 and item \
% 5 != 0 and item % 6 != 0 and item % 7 != 0 and item % 8 != 0 \
and item % 9 != 0:
primelist.append(item)
return primelist
def greatestprime(n):
list = prime(n)
list[0] = lnum
i = 1
while i < len(list):
if list[i] > lnum:
lnum = list[i]
return lnum
#print(greatestprime(600851475143))
答案 0 :(得分:2)
如果您只对一个数字n
进行分解,那么测试从2到sqrt(n)
(n
的平方根)的每个数字的天真方法应该可以快速得出数字至10 14 。您编写的代码超出了必要的范围。
稍微好一点的方法是:
稍微更好的方法是通过Eratosthenes筛子和测试(无冗余测试)生成质数。除了使用更多数字之外,还有更好的方法,例如Pollard's rho因子分解,但这两种方法都是过度的。
答案 1 :(得分:2)
找到一个数字中最大的素数因子并不像人们想象的那么困难。
from itertools import takewhile
from math import floor, sqrt
def _prime_numbers_helper():
yield 2
yield 3
i = 1
while True:
yield 6 * i - 1
yield 6 * i + 1
i += 1
def prime_numbers(ceiling=None):
if ceiling is None:
yield from _prime_numbers_helper()
else:
yield from takewhile(lambda number: number <= ceiling, _prime_numbers_helper())
def largest_prime_factor(number):
if number % int(number) != 0:
raise ValueError('The number must be an integer.')
if number in (0, 1):
raise ValueError('There is no largest prime factor of {}.'.format(number))
while True:
for i in prime_numbers(floor(sqrt(abs(number)))):
if number % i == 0:
number //= i
break
else:
return number
else
语句仅在for
语句执行完成时执行(即,当数字无法进一步计算时)。
for
语句应使用真正的素数生成器,但是我懒得写一个有效的实现。
请注意,这假设您使用的是Python 3.3或更高版本。
出于好奇,这是项目欧拉问题3?
答案 2 :(得分:2)
只要 n 不是太大,就很容易通过试验分找到 n 的因子; ::
运算符在 fs 链接列表的前面插入 f :
function factors(n)
f, fs := 2, []
while f * f <= n
while n % f == 0
n := n / f
fs := f :: fs
f := f + 1
if n <> 1
n :: fs
return reverse(fs)
如果您对使用素数进行编程感兴趣,或者您正在寻找一个库以帮助解决涉及素数的Project Euler问题,我谦虚地在我的博客上推荐this essay,其中包括:除其他外,将上述伪代码翻译成Python:
def td_factors(n, limit=1000000):
if type(n) != int and type(n) != long:
raise TypeError('must be integer')
fs = []
while n % 2 == 0:
fs += [2]
n /= 2
if n == 1:
return fs
f = 3
while f * f <= n:
if limit < f:
raise OverflowError('limit exceeded')
if n % f == 0:
fs += [f]
n /= f
else:
f += 2
return fs + [n]
答案 3 :(得分:2)
这有两种可能性。一个来自this blog:
def gpf(n):
"""
Find the greatest prime factor of n
"""
if n < 2:
raise ValueError('{} does not have a prime factorization'.format(n))
divisor = 2
while n > 1:
if not n % divisor:
n /= divisor
divisor -= 1
divisor += 1
return divisor
你的例子:
In [15]: gpf(600851475143)
Out[15]: 6857
In [16]: timeit gpf(600851475143)
1000 loops, best of 3: 1.55 ms per loop
或使用SymPy
库:
from sympy import factorint
def gpf(n):
return max(factorint(n).keys())
(请注意,这已定义了n&lt; 2)
的行为答案 4 :(得分:1)
这就是我的方式:
def is_prime(m):
"""Checks if the argument is a prime number."""
if m < 2: return False
for i in xrange(2, m):
if m % i == 0:
return False
return True
def get_largest_prime_factor(k):
"""Gets the largest prime factor for the argument."""
prime_divide = (p for p in xrange(1, k))
for d in prime_divide:
if k % d == 0 and is_prime(k / d):
return k / d
print get_largest_prime_factor(600851475143)
答案 5 :(得分:1)
尝试:
number = whatever your number is
divisor = 2
while divisor < number:
if number % divisor == 0:
number /= divisor
else:
divisor += 1
你将数字分开,直到它不再可能 - 这就是他们教你在小学就这类问题所做的事情(尽管他们从不要求你这样做12位数的技巧)。当你得到一个
的数字起初看起来很奇怪,但它确实有效:每次通过你都会减少你正在查看的数字的大小并分割掉较小的素数。例如,如果数字可以被32整除,那么在继续之前你只需要将6次除以6次,这样你就可以缩小可以成为因子的数字池number
。如果您的号码已经是其最大的主要因素,那么您仍然必须迭代它才能验证这一点。在正常情况下(number
是其最大素数和某些复合数的乘积),在你检查最大素数除以它之前,你将其所有较小的因子分开。
另一个有用的启发式方法是找到你的数字的平方根,只检查小于它的数字:n > sqrt(number)
n
number
的{{1}}是({整数)因子{{1} }}。不过,我喜欢第一种方法。
答案 6 :(得分:1)
n=int(input(""))
prime_factors=[]
for i in range(2,int(n**0.5+1)):
if n%i==0:
for x in range(2,int(i**0.5+1)):
if i%x==0:
break
else:
prime_factors.append(i)
print("prime factors are:",prime_factors)
print("largest prime factor is",prime_factors[-1])
输入:600851475143
输出:质因数为:[71, 839, 1471, 6857]
最大的质因数是 6857
答案 7 :(得分:0)
实际最终计划:使用长划分方法查找因素 并且只存储最大/当前因子,直到找到最后一个因子。
我知道这是一个老问题,但我想分享我解决问题的方法。
def prime_factors_old_fashioned_factorization(number):
y=1
for x in range(2,number):
if(number%x==0):
print("number=",number,"\t and X=",x)
while(number%x==0):
print("number=",number)
number=number/x
print("new number=",number)
y=x
x=x+1
if((number==1) or (number<x)):
break;
print("largest prime factor=",y)
答案 8 :(得分:0)
AVPlayer