数字的除数:如何改进此代码以查找大数的除数?

时间:2017-04-28 14:47:35

标签: python math

对于非常大的数字,我的代码非常慢。

def divisors(num):
    divs = 1
    if num == 1:
        return 1

    for i in range(1, int(num/2)):
        if num % i == 0:
            divs += 1
        elif int(num/2) == i:
            break
        else:
            pass
    return divs

对于10 ^ 9,我的运行时间为381.63秒。

4 个答案:

答案 0 :(得分:3)

这是一种确定n的各种不同素因子的多重性的方法。每个此类权力k对除数总数的贡献为k+1

import math

def smallest_divisor(p,n):
    #returns the smallest divisor of n which is greater than p
    for d in range(p+1,1+math.ceil(math.sqrt(n))):
        if n % d == 0:
            return d
    return n

def divisors(n):
    divs = 1
    p = 1
    while p < n:
        p = smallest_divisor(p,n)
        k = 0
        while n % p == 0:
            k += 1
            n //= p
        divs *= (k+1)
    return divs - 1

它返回适当除数的数量(因此不计算数字本身)。如果要计算数字本身,请不要从结果中减去1。

它可以使用10 ** 9的数字快速工作,但是如果数字更大则会显着减慢。

答案 1 :(得分:0)

考虑一下:

import math

def num_of_divisors(n):
    ct = 1
    rest = n
    for i in range(2, int(math.ceil(math.sqrt(n)))+1):
        while rest%i==0:
            ct += 1
            rest /= i
            print i  # the factors
        if rest == 1:
            break
    if rest != 1:
       print rest   # the last factor
       ct += 1
    return ct

def main():
    number = 2**31 * 3**13
    print '{} divisors in {}'.format(num_of_divisors(number), number)

if __name__ == '__main__':
    main()

我们可以停止在n的平方根处搜索因子。在while循环中找到了多个因子。当找到一个因子时,我们将其从数字中除去 修改
@Mark Ransom是对的,对于一个因子大于该数字的平方根的数字,因子计数为1太小,例如3*47*149*6991rest != 1的最后一次检查说明了这一点。 因素的数量确实是正确的 - 您不必为了sqrt(n)而检查。{ 如果需要,可以使用打印数字的两个语句将此数字附加到因子数。

答案 2 :(得分:0)

分区很贵,乘法便宜。

将数字分解为素数。 (下载素数列表,继续与<= sqrt(num)分开。)

然后计算所有排列。

如果你的数字恰好是一个素数p^n的幂,你就可以得到n除数,不包括1; 8 = 2 ^ 3有3个除数:8,4,2。

一般情况下,您的数字因素为k素数:p0^n0 * p1^n1 * ... * pk^nk。它有(n0 + 1) * (n1 + 1) * .. * (nk + 1)个除数。 &#34; + 1&#34;当所有其他幂为0时的情况下的术语计数,即对乘法贡献1。

或者,你可以谷歌和RTFM

答案 3 :(得分:0)

以下是我在问题中的代码的改进版本。运行时间更好,现在为10 ^ 9,为0.008s。

def divisors(num):
    ceiling = int(sqrt(num))
    divs = []
    if num == 1:
        return [1]
    for i in range(1, ceiling + 1):
        if num % i == 0:
            divs.append(num / i)
            if i != num // i:
                divs.append(i)
    return divs
  

对我来说,保持除数很重要,所以如果这仍然可以   得到改善我很高兴。