你将如何实现除数函数?

gyo*_*sko 3 python math numbers

除数函数是一个自然数的约数的总和.

进行一些研究我发现如果你想找到给定自然数N的除数函数,是一个非常好的方法,所以我试着用Python编写代码:

def divisor_function(n):
    "Returns the sum of divisors of n"
    checked = [False]*100000
    factors = prime_factors(n)
    sum_of_divisors = 1 # It's = 1 because it will be the result of a product
    for x in factors:
        if checked[x]:
            continue
        else:
            count = factors.count(x)
            tmp = (x**(count+1)-1)//(x-1)
            sum_of_divisors*=tmp
            checked[x]=True
    return sum_of_divisors
Run Code Online (Sandbox Code Playgroud)

它工作得很好,但我确信它可以改进(例如:我创建一个包含100000元素的列表,但我没有使用它们中的大部分).

你会如何改进/实施它?

PS这是prime_factors:

def prime_factors(n):
    "Returns all the prime factors of a positive integer"
    factors = []
    d = 2
    while (n > 1):
        while (n%d==0):
            factors.append(d)
            n /= d
        d = d + 1
        if (d*d>n):
            if (n>1): factors.append(int(n));
            break;
    return factors
Run Code Online (Sandbox Code Playgroud)

Gar*_*ees 8

计算除数之和时,需要以p 1 k 1 p 2 k 2 ... 的形式n进行因式分解- 也就是说,需要分解中每个素数的指数.目前,你通过计算一个素数因子的平面列表,然后调用计算指数来做到这一点.这是浪费时间,因为您可以首先以您需要的格式轻松生成素数分解,如下所示: count

def factorization(n):
    """
    Generate the prime factorization of n in the form of pairs (p, k)
    where the prime p appears k times in the factorization.

    >>> list(factorization(1))
    []
    >>> list(factorization(24))
    [(2, 3), (3, 1)]
    >>> list(factorization(1001))
    [(7, 1), (11, 1), (13, 1)]
    """
    p = 1
    while p * p < n:
        p += 1
        k = 0
        while n % p == 0:
            k += 1
            n //= p
        if k:
            yield p, k
    if n != 1:
        yield n, 1
Run Code Online (Sandbox Code Playgroud)

关于上面代码的注释:

  1. 我已经转换了这段代码,以便生成分解,而不是构建一个列表(通过重复调用append)并返回它.在Python中,这种转换几乎总是一种改进,因为它允许您在生成元素时逐个使用它们,而不必将整个序列存储在内存中.

  2. 这是doctests运行良好的功能.

现在计算除数之和非常简单:不需要存储检查因子集或计算每个因子出现的次数.事实上,你可以只用一行:

from operator import mul

def sum_of_divisors(n):
    """
    Return the sum of divisors of n.

    >>> sum_of_divisors(1)
    1
    >>> sum_of_divisors(33550336) // 2
    33550336
    """
    return reduce(mul, ((p**(k+1)-1) // (p-1) for p, k in factorization(n)), 1)
Run Code Online (Sandbox Code Playgroud)