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除非通过迭代或调用列表(或类似)来请求其值,否则不要执行任何操作