2

我编写了以下程序来对一个数字进行质因数分解:

import math
def prime_factorize(x,li=[]):
    until = int(math.sqrt(x))+1
    for i in xrange(2,until):
        if not x%i:
            li.append(i)
            break
    else:                      #This else belongs to for
        li.append(x)
        print li               #First print statement; This is what is returned
        return li
    prime_factorize(x/i,li)

if __name__=='__main__':
    print prime_factorize(300)   #Second print statement, WTF. why is this None

以下是我得到的输出:

 [2, 2, 3, 5, 5]
 None

Altho',返回值被正确打印,之后的返回值似乎一直没有打印。我错过了什么?

另外,如何改进程序(继续使用递归)

4

6 回答 6

9

您的 prime_factorize 函数在递归情况下没有 return 语句——您想在其最后一行调用“return prime_factorize(x/i,li)”。尝试使用素数(因此不需要递归调用)以查看它在这种情况下是否有效。

此外,您可能希望使签名类似于:

def prime_factorize(x,li=None):
    if li is None: li = []

否则在调用它两次或多次时会得到错误的结果:

>>> prime_factorize(10)
[2, 5]
>>> prime_factorize(4)
[2, 5, 2, 2]
>>> prime_factorize(19)
[2, 5, 2, 2, 19]
于 2009-09-12T08:05:27.873 回答
9

如果你想完全递归,我推荐这段代码,它确实返回正确的答案,而且它的工作方式很清楚。如果您想让程序尽可能高效,我建议您坚持使用以前的方法之一。

def primeFact (i, f):
    if i < f:
        return []
    if i % f == 0:
        return [f] + primeFact (i / f, 2)
    return primeFact (i, f + 1)

这是解决问题的完全递归方式

>>> primeFact (300, 2)
[2, 2, 3, 5, 5]
>>> primeFact (17, 2)
[17]
>>> primeFact (2310, 2)
[2, 3, 5, 7, 11]
于 2012-10-31T21:46:45.407 回答
3

@Anthony 正确回答了您关于print. 然而,本着还提供的几个技巧的精神,这里有一个使用尾递归删除的简单重构:

def prime_factorize(x):
  li = []
  while x >= 2:
    until = int(math.sqrt(x))+1
    for i in xrange(2,until):
      if not x%i:
        li.append(i)
        break
    else:
      li.append(x)
      return li
    x //= i

这并没有解决关键的性能问题(big-O 行为与您的原始解决方案相同)——但由于 Python 本身不进行尾递归优化,因此学习手动进行优化很重要。

“将[非基本情况]递归步骤'return thisfun(newargs)'改为args=newargs; continue整个while True:循环”是尾递归优化的基本思想。在这里,我还使 li 成为非 arg (没有理由让它成为 arg),在 上设置一个条件while,并避免了,continue因为递归步骤无论如何都在正文的末尾。

该公式将成为应用进一步优化重构(避免sqrt、记忆化等)以达到更好性能的良好基础。

于 2009-09-12T15:04:33.020 回答
2

更实用的版本。

def prime_factorize( number ):
    def recurse( factors, x, n ):
        if x<2: return factors # 0,1 dont have prime factors
        if n > 1+x**0.5: # reached the upper limit
            factors.append( x ) # the only prime left is x itself
            return factors
        if x%n==0: # x is a factor
            factors.append( n )
            return recurse( factors, x/n, n )
        else:
            return recurse( factors, x, n+1 )
    return recurse( [], number, 2)

for num, factors in ((n, prime_factorize( n )) for n in range(1,50000)):
    assert (num==reduce(lambda x,y:x*y, factors, 1)), (num, factors)
    #print num, ":", factors
于 2009-09-12T13:59:57.537 回答
0
def primeFactorization(n):
    """ Return the prime factors of the given number. """
    factors = []
    lastresult = n
    while 1:
        if lastresult == 1:
            break

        c = 2

        while 1:
            if lastresult % c == 0:
                break

            c += 1

        factors.append(c)
        lastresult /= c

    return factors

好吗?

于 2011-08-09T06:24:34.077 回答
0
def Pf(n,i):

  if n%2==0:
        print(2)
        Pf(n/2,3)
  elif n<i:
      return 0

  else:

  
      if n%i==0:
        print(i)
        Pf(n/i,i)
      else:
        Pf(n,i+2)
n=int(input())
Pf(n,3)

看看这段代码

于 2021-05-06T08:07:11.227 回答