如何用最简单的Python方法找出一个数的因数

-3 投票
3 回答
2103 浏览
提问于 2025-04-18 17:11

如何找到一个数字的所有因子,并把这些因子列成一个列表。

输入:

   >>>factors(72)

输出:

   [2, 2, 2, 3, 3]

我把一些代码删掉了,因为这个问题被很多人关注,而且这是一个作业问题,所以我不想让它被复制。

3 个回答

0

这里有一个使用质数分解的解决方案。这个方法要快得多。

import bisect
import math
import pathlib


primes = []
last_prime = None


def _get_primes():
    """
    Load all the primes in global primes. Set global last_prime to last prime
    read.
    """

    global primes
    global last_prime
    path_to_primes = pathlib.Path(__file__).parent \
            .joinpath('../resources/primes.txt')
    with path_to_primes.open() as file:
        for line in file:
            for n in line.split():
                n = n.strip()
                if n:
                    n = int(n)
                    primes.append(n)
    last_prime = primes[-1]


def gen_primes_before(n):
    """
    Generates all the primes before n in reverse order.
    """

    assert n <= last_prime, "Maximum value for n is {}".format(last_prime)
    pos = bisect.bisect_left(primes, n)
    if pos:
        yield from primes[:pos]


def gen_factors(n):
    """
    Generates all the factors of a number. May return some values multiple
    times. Values returned are not ordered.
    """
    type_n = type(n)
    assert type_n is int or (type_n is float and n.is_integer()), "Wrong type"
    n = int(n)
    r = int(math.sqrt(n)) + 1
    assert r <= last_prime, "n is over limit"
    yield 1
    yield n
    for prime in gen_primes_before(r):
        partner = n/prime
        if partner.is_integer():
            yield from gen_factors(prime)
            yield from gen_factors(partner)


def get_factors(n):
    """
    Get all the factors of n as a sorted list.
    """
    return sorted(set(gen_factors(n)))


_get_primes()
if __name__ == '__main__':
    l = (1e9,)
    for n in l:
        print("The factors of {} are {}".format(n, get_factors(n)))

我创建了一个代码库:https://github.com/Pierre-Thibault/Factor

1

关于你的第一个问题:因式分解是很难的。这就是为什么它在许多加密算法中占据核心地位——目前我们还不知道有什么方法可以快速地对一个非常大的数字进行因式分解。

对于小数字,你的算法可以用。对于稍微大一点的数字,我也有过同样的问题——显然,Pollard's Rho算法在这方面表现不错。至于大数字,我们现在还没有好的办法。

接下来是你的第二个问题:

首先,在你的prime(n)函数中,你不需要检查if n%i==0一直到n。你只需要检查到sqrt(n)就可以了,因为如果有一对整数(a,b)使得a * b = n,那么这两个整数中必有一个会小于或等于sqrt(n)。所以你只需要检查到sqrt(n),这样可以节省很多计算。

这是你的factors函数:

from math import ceil

def factors(n):
        factors = []
        while n > 1:
                for i in range(2,int((ceil(n/2.0))+1)):
                        if n%i==0:
                                factors.append(i)
                                n = n/i
                                continue
                factors.append(n)
                break
        return factors
1
def factors(n):
a = []
x = 2
while x * x <= n :
    if n % x == 0:          
        a.append(x)
        n /= x
    else: x += 1
if n > 1: a.append(n)
return a

所有的内容都被迅速地点了踩。

撰写回答