最大的Prime Factor Python

时间:2014-02-10 18:04:08

标签: list python-3.x primes prime-factoring

我正在尝试使用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))

9 个答案:

答案 0 :(得分:2)

如果您只对一个数字n进行分解,那么测试从2到sqrt(n)n的平方根)的每个数字的天真方法应该可以快速得出数字至10 14 。您编写的代码超出了必要的范围。

稍微好一点的方法是:

  • 测试2,然后测试每个奇数
  • 测试2,3,5,然后测试形式为6k + 1和6k + 5的所有整数,其中k> = 1
  • 上述两种方法是wheel factorization,n = 2且n = 2 * 3 = 6。你可以把它提升到n = 2 * 3 * 5 * 7 = 210(更高不会带来太多效率)。

稍微更好的方法是通过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