Python 一个数的除数:我如何改进这段代码以找到大数的除数?

Python 一个数的除数:我如何改进这段代码以找到大数的除数?,python,math,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

当涉及到非常大的数字时,我的代码非常慢

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.63s的运行时间。

考虑一下:

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是对的,对于一个因子大于数字平方根的数字,因子计数太小,例如
3*47*149*6991
rest!=1
说明了这一点。 那么,因子的数量确实是正确的-您不必为此检查超出
sqrt(n)


如果需要,打印数字的两个语句都可以用于将该数字附加到因子数。

这里有一种方法,可以确定
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
导入数学
def最小除数(p,n):
#返回n中大于p的最小除数
对于范围内的d(p+1,1+math.ceil(math.sqrt(n)):
如果n%d==0:
返回d
返回n
def除数(n):
divs=1
p=1
而p
它返回正确的除数(因此不计算数字本身)。如果你想计算数字本身,不要从结果中减去1


它可以快速处理大小为10**9的数字,但对于更大的数字,速度会显著减慢。

除法很昂贵,乘法很便宜


把这个数分解成素数。(下载素数列表,继续从
中分割。这是我的问题代码的一个改进版本。运行时间更好,现在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
保留除数对我来说很重要,所以如果这仍然可以 如果能有所改进,我会很高兴的


试图破解RSA?;)@CongMa还没有;)如果停止在平方根处搜索,则只会计算一半的因子。如果你试图解释这一点,你将很容易受到一个错误的影响。你是对的,如果最后的余数大于一,那么它也是一个因素(1在开头以
ct=1
隐式假设)。我已经更正了我的代码,谢谢。对于您关于
sqrt(n)
,您能给我一个脚本返回错误计数的数字示例吗?请尝试
num\u of_除数(5)
num\u of_除数(25)
,以及
num\u of_除数(125)
。您是对的,在
范围()中有一个一次性错误,因为上限不包括在内。代码在一个平方数上会失败。修正了。没有必要将电源保持在list@Copperfield当然,你是对的。我这样做最初是因为我想检查它们,以确保我的逻辑正确。我将调整代码以保持产品的运行。谢谢。@Copperfield做得很好,我终于找到了一个更快的解决方案,我的代码运行时间下降到大约0.008s,持续10^9秒。正如你可以从我下面的代码中看到的,它花费了相当多的时间来寻找除数。您的代码是否也可以修改以获得除数?我正在研究,但是如果你能帮***如果你想找到除数而不是它们的数目,你可以按照下面的方法,在这两种情况下,最好的方法是将number@Copperfield谢谢,但我已经去了那里,我从那里得到的最好的代码与我的代码运行时间相同,但是Tomas Kulich的代码让我在运行时有了这个想法,我的声誉不允许我直接评论他的答案来解决问题。generator除非通过迭代或调用列表(或类似)来请求其值,否则不要执行任何操作