素数因子化python

时间:2015-02-07 13:04:29

标签: python primes prime-factoring

我是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质量的东西?我在笔记本电脑上运行程序。

5 个答案:

答案 0 :(得分:3)

你的问题肯定不是数字小到864的复杂性。相反,当你这样做时:

while functools.reduce(operator.mul, factorlist, 1) != a:
    for x in range (1, a):
        ...

你所做的事情实际上是在每次不减少的情况下经历所有可能的素数。这是多余的,因为您只需要遍历列表一次。

对于像2000这样的输入,你进入一个无限循环,因为它永远不会减少到2000 - 这就是为什么它一直在运行。您可以在print factorlistwhile之间添加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)