繁体   English   中英

使用递归4 *(1-(1/3)+(1/5)-(1/7)+(1/9)-(1/11)…来近似此方程式

[英]Approximate this equation using recursion 4 * (1 - (1 /3 ) + (1 / 5) - (1 / 7) + (1 / 9) - (1 / 11) … )

如何使用递归来近似以下方程式? 这是一种迭代方法:

def calculateFrac(num):
    result = 0
    for i in range(num):
        if i % 2 == 0:
            result = result + 1 / (2 * i + 1)
        else:
            result = result - 1 / (2 * i + 1)
        print(4 * result)

print(calculateFrac(10))

首先,您也不会返回结果。 这是您代码的固定版本。

def calculateFrac(num):
    result = 0
    for i in range(num):
        if i % 2 == 0:
            result = result + 1 / (2 * i + 1)
        else:
            result = result - 1 / (2 * i + 1)

    return result # return the result instead of printing it

print(calculateFrac(10)) # 0.7604599047323508

从那里开始,上面的代码非常完美。

不要使用递归

虽然,请注意,用sumgenerator更好地表示无限级数,而不是递归。 特别是在无法优化尾递归的 Python中。

递归解决方案将变慢,使用更多内存并最终达到最大递归深度。

from itertools import islice, count

def seq():
    for n in count():
        yield (-1) ** n / (2 * n + 1)

print(sum(islice(seq(), 0, 10))) # 0.7604599047323508

递归练习

看来您想学习使用递归。 因此,重要的是,您还应确定不需要有效递归的问题。

递归通常更适合每次迭代都会产生问题的问题。 也就是说形式F(N)的问题= F(N 1)+ F(N 2),其中N 1N 2N个子集。 一个常见的例子是mergesort

您可以在线找到许多此类问题的习题集

def calculateFraction(num):
  if (num > 0):
    return (-1)**(num) * 1/(num*2+1) + calculateFraction(num-1)
  else:
    return 1

print(4 * calculateFraction(10))

编辑

Olivier的回答非常好,我希望我可以多次投票。

有鉴于此,我认为OP可能会受益于上述方法的二进制实现。 也就是说,每当递归时,将问题的一半发送到一个分支,另一半发送到另一个分支。 (这意味着,例如,请求num = 15将导致深度为4而不是深度为16。)

import inspect

def calculateFraction(num, end=0):
    result = 0
    depth = 'Depth({:d}){:s}>'.format(len(inspect.stack())-1, '='*(len(inspect.stack())-1)*2)

    # If there are an odd number of parts to calculate, do the highest one now
    if (((num-end+1)&1) == 1):
        result += ((-1)**(num)) / (num*2+1)
        print('{:s} Fraction part {:d} = {:f}'.format(depth, num, result))
        num-=1

    # If there are still any parts to calculate, do them recursively
    # (There must be an even number, as we did the odd one previously)
    # (That may leave 0 still to do, in which case the recursion is skipped)
    if (num > end):
        mid = ((num-end)>>1) + end

        # Do the upper half of the remaining parts
        print('{:s} Recursing to {:d},{:d}'.format(depth, num, mid+1))
        result += calculateFraction(num, mid+1)

        # Do the lower half of the remaining parts
        print('{:s} Recursing to {:d},{:d}'.format(depth, mid, end))
        result += calculateFraction(mid, end)

    return result

print('Result: {:f}'.format(4*calculateFraction(10)))

我在问如何使用递归解决这个问题。

我不同意@OlivierMelançon所说的这是一个糟糕的递归示例。 我仅提供了一种可怕的递归解决方案的可能实现:

def calculateFrac(num):
    if num < 1:
        return 0.0

    return calculateFrac(num - 1) + (2 * (num % 2) - 1) / (2 * num - 1)

print(calculateFrac(10))  # 0.7604599047323508 (put in the 4 *)

在我的系统上,它可以处理的最大参数是997,而无需通过sys.setrecursionlimit()显式扩展调用堆栈。 使用记忆技术将无济于事。 我们可以通过执行以下操作来制作尾递归解决方案:

def calculateFrac(num, sum=0.0):
    if num < 1:
        return sum

    return calculateFrac(num - 1, sum + (2 * (num % 2) - 1) / (2 * num - 1))

print(calculateFrac(10))  # 0.7604599047323506 (put in the 4 *)

并不是说Python关心这样的事情。 但是,如果确实进行了尾部调用优化,则诸如解决方案的速度可能与迭代解决方案一样快,并且没有任何堆栈限制。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM