Python递归程序对数字进行质因数分解

发布于 2024-08-05 02:54:15 字数 670 浏览 4 评论 0原文

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

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

虽然,返回值打印正确,但返回后的值似乎始终不打印任何内容。我缺少什么?

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

I wrote the following program to prime factorize a number:

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

Following is the output I get:

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

Altho', the returned value is printed properly, the after returned value seems to be printing none, all the time. What am I missing?

Also, how can I improve the program (continuing to use the recursion)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

那片花海 2024-08-12 02:54:15

您的 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]

Your prime_factorize function doesn't have a return statement in the recursive case -- you want to invoke "return prime_factorize(x/i,li)" on its last line. Try it with a prime number (so the recursive call isn't needed) to see that it works in that case.

Also you probably want to make the signature something like:

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

otherwise you get wrong results when calling it two or more times:

>>> prime_factorize(10)
[2, 5]
>>> prime_factorize(4)
[2, 5, 2, 2]
>>> prime_factorize(19)
[2, 5, 2, 2, 19]
请叫√我孤独 2024-08-12 02:54:15

如果您想完全递归地执行此操作,我会推荐此代码,它确实返回正确的答案,并且其工作方式非常清晰。
如果您想让程序尽可能高效,我建议您坚持使用以前的方法之一。

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]

If you want to do it completely recursive, I'd recommend this code, it does return the correct answer and the way it works is pretty clear.
If you want to make the program as efficient as possible I'd recommend you to stick to one of your previous methods.

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

This is a completely recursive way of solving your problem

>>> primeFact (300, 2)
[2, 2, 3, 5, 5]
>>> primeFact (17, 2)
[17]
>>> primeFact (2310, 2)
[2, 3, 5, 7, 11]
素衣风尘叹 2024-08-12 02:54:15

@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

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

“将[非基本情况]递归步骤'return thisfun(newargs)'更改为args=newargs; continue并将整个主体放入while中True:loop”是尾递归优化的基本思想。在这里,我还使 li 成为非参数(没有理由让它成为参数),在 while 上放置一个条件,并避免自递归以来的 continue无论如何,步骤是在身体的末端。

该公式将成为应用进一步优化重构(避免平方根、记忆化……)以实现更好性能的良好基础。

@Anthony's correctly answered your original question about print. However, in the spirit of the several tips that were also offered, here's a simple refactorization using tail recursion removal:

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

This doesn't address the crucial performance issues (big-O behavior is the same as for your original solution) -- but since Python itself doesn't do tail-recursion optimization, it's important to learn to do it manually.

"Change the [non-base-case] recursive steps 'return thisfun(newargs)' into args=newargs; continue and put the whole body into a while True: loop" is the basic idea of tail-recursion optimization. Here I've also made li a non-arg (no reason for it to be an arg), put a condition on the while, and avoided the continue since the recursive step was at the end of the body anyway.

This formulation would be a good basis from which to apply further optimizing refactorings (sqrt avoidance, memoization, ...) to reach towards better performance.

挥剑断情 2024-08-12 02:54:15

更加实用的风格版本。

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

A more functional-style version.

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
从﹋此江山别 2024-08-12 02:54:15
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

可以吗?

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

is it fine.

木落 2024-08-12 02:54:15
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)

看看这个代码

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)

check out this code

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文