查找数字优化的所有除数

时间:2012-09-14 09:43:17

标签: python math mathematical-optimization

我编写了以下函数,该函数查找给定自然数的所有除数并将它们作为列表返回:

def FindAllDivisors(x):
    divList = []
    y = 1
    while y <= math.sqrt(x):
        if x % y == 0:
            divList.append(y)
            divList.append(int(x / y))
        y += 1
    return divList

它的效果非常好,但输入是一个18位数的时候它真的很慢。你对我如何加快它有什么建议吗?

更新

我有以下方法来检查基于费马小定理的素数:

def CheckIfProbablyPrime(x):
    return (2 << x - 2) % x == 1

这种方法在检查单个数字时非常有效,但是我不确定是否应该使用它来编译所有素数直到某个边界。

4 个答案:

答案 0 :(得分:23)

您可以通过计算素数因子分解找到数字的所有除数。每个除数必须是因子分解中素数的组合。

如果您有素数列表,这是获得因子分解的简单方法:

def factorize(n, primes):
    factors = []
    for p in primes:
        if p*p > n: break
        i = 0
        while n % p == 0:
            n //= p
            i+=1
        if i > 0:
            factors.append((p, i));
    if n > 1: factors.append((n, 1))

    return factors

这称为试验分裂。有更有效的方法来做到这一点。有关概述,请参阅here

现在计算除数非常简单:

def divisors(factors):
    div = [1]
    for (p, r) in factors:
        div = [d * p**e for d in div for e in range(r + 1)]
    return div

计算所有除数的效率取决于找到素数(小概述here)和分解算法的算法。对于非常大的数字,后者总是很慢,而且你可以做的不多。

答案 1 :(得分:3)

我建议将math.sqrt(x)的结果存储在单独的变量中,然后针对它检查y。否则,它将在while的每一步重新计算,而math.sqrt绝对不是轻量级操作。

答案 2 :(得分:1)

我会进行素因子分解,然后计算该结果中的所有除数。

答案 3 :(得分:0)

我不知道是否有很多性能损失,但我很确定转换为int是不必要的。至少在Python 2.7中,int x / int y返回一个int。