我是python的新手,我认为我会创建一个程序来返回给定数字的素数因子。这是我的代码:
import math
import operator
import functools
def isprime (n):
if n == 1:
return False
elif n == 2:
return True
else:
for x in range (2, int(math.sqrt(n))+1):
if n % x == 0:
return False
break
else:
return True
def factors (a):
factorlist = []
if isprime(a) == True:
print "The number is a prime."
else:
while functools.reduce(operator.mul, factorlist, 1) != a:
for x in range (1, a):
if a % x == 0:
if isprime(x) == True:
factorlist.append(x)
factorlist.sort()
print factorlist
testnumber = int(input("Enter a number."))
factors(testnumber)
我的问题是,根据号码,需要很长时间。它可以立即解决100或1000,但2000或864只是不起作用!我让它以864作为我的输入运行了45分钟,但它没有打印任何东西。是我的CPU质量的东西?我在笔记本电脑上运行程序。
答案 0 :(得分:3)
你的问题肯定不是数字小到864的复杂性。相反,当你这样做时:
while functools.reduce(operator.mul, factorlist, 1) != a:
for x in range (1, a):
...
你所做的事情实际上是在每次不减少的情况下经历所有可能的素数。这是多余的,因为您只需要遍历列表一次。
对于像2000这样的输入,你进入一个无限循环,因为它永远不会减少到2000 - 这就是为什么它一直在运行。您可以在print factorlist
和while
之间添加for
,以确切了解正在发生的事情。
如果您只删除while
声明,则可以更快地获得结果。
(请注意,我同意费迪南德·拜尔关于上面的大数字的评论。我只是说在你的具体情况下,864并不是一个很大的数字,并且那里有#sa;程序中的错误。)
答案 1 :(得分:1)
这是最快的一个;
n = 600851475143
i = 2
while i * i < n:
while n%i == 0:
n /= i
print (i)
i += 1
您可以在here中找到此方法的说明。 n
是数字和i
素因子。
答案 2 :(得分:1)
您的代码存在的问题是您在通话functools.reduce(operator.mul, factorlist, 1)
中反复进行一些昂贵的计算,并且您反复检查isprime(x)
是否有相同的数字(和{{由于循环,1}}本身很昂贵。
要避免isprime
来电,您可以通过改变您在@ howaboutNO解决方案中考虑的数字,或者通过进行递归调用来简单地划分已知因素(请参阅下文) )。
为了避免使用相同的值调用functools.reduce
的费用,您可以使用memoization,这是您的工具集中的一个方便技巧。
应用这两个,我想出了以下内容:
isprime(x)
比你的代码运行得快得多。
答案 3 :(得分:1)
这是基于模块筛的更快的分解:
# modular sieve based on (2,3,5):
sieve_size = 2 * 3 * 5
sieve = [1, 7, 11, 13, 17, 19, 23, 29]
# all primes < sieve_size
base = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
def factors(a):
f = []
# remove factors of primes < sieve_size
for b in base:
while not a % b:
a //= b
f.append(b)
if a < b*b:
break
# remnant fully factored?
if a < b*b:
if a > 1:
f.append(a)
return f
# remove factors of values generated by modular sieve
# (We do not need to test for actual primality;
# because candidate values are generated in ascending order,
# if the value is composite, all factors of it will have
# already been removed)
n = sieve_size
while True:
for s in sieve:
b = n + s # 31, 37, 41, 43, ...
while not a % b:
a //= b
f.append(b)
if a < b*b:
break
if a < b*b:
if a > 1:
f.append(a)
return f
n += sieve_size
然后快速测试:
import random
for i in range(30):
val = random.randint(1000, 1000000)
print(val, factors(val))
几乎立即给出了
344779 [73, 4723]
376343 [11, 34213]
830823 [3, 7, 39563]
927157 [7, 11, 12041]
852641 [852641]
802619 [47, 17077]
80214 [2, 3, 29, 461]
348030 [2, 3, 3, 3, 5, 1289]
533572 [2, 2, 13, 31, 331]
317206 [2, 199, 797]
806636 [2, 2, 421, 479]
539294 [2, 7, 7, 5503]
706820 [2, 2, 5, 59, 599]
501587 [97, 5171]
759410 [2, 5, 75941]
375319 [7, 53617]
668889 [3, 3, 13, 5717]
545731 [545731]
496852 [2, 2, 124213]
309332 [2, 2, 17, 4549]
629728 [2, 2, 2, 2, 2, 11, 1789]
835342 [2, 417671]
505591 [71, 7121]
172411 [172411]
410995 [5, 13, 6323]
645451 [31, 47, 443]
369849 [3, 113, 1091]
67237 [71, 947]
505186 [2, 11, 22963]
945547 [945547]
答案 4 :(得分:0)
除非您将其用作编程练习,否则只需使用
primefactors(testnumber)